My solution for the Challenge

#import <limits.h>
#import "NSData+Speakable.h"

static const NSArray *brandNames = nil;

@implementation NSData (Speakable)

+ (void)initialize
{
    if (!brandNames) {
        brandNames = @[@"Camry", @"Nikon", @"Apple", @"Ford", @"Audi", @"Google", @"Nike", @"Amazon", @"Honda",
            @"Mazda", @"Buick", @"Fiat", @"Jeep", @"Lexus", @"Volvo", @"Fuji", @"Sony", @"Delta", @"Focus", @"Puma",
            @"Samsung", @"Tivo", @"Halo", @"Sting", @"Shrek", @"Avatar", @"Shell", @"Visa", @"Vogue", @"Twitter",
            @"Lego", @"Pepsi"];
    }
}

- (NSString *)encodeAsSpeakableString
{
    NSMutableString *speakableString = [NSMutableString new];
    [self enumerateByteRangesUsingBlock:^(const void *bytes, NSRange byteRange, BOOL *stop) {
        const unsigned char *arrayOfBytes = bytes;
        for (NSInteger i = 0; i < byteRange.length; i++) {
            NSString *encodedByte = [self encodeSingleByte:arrayOfBytes[i]];
            [speakableString appendString:encodedByte];
        }
    }];
    return speakableString;
}

- (NSString *)encodeSingleByte:(unsigned char)byte
{
    unsigned char left3 = byte >> 5;
    unsigned char right5 = byte & 0x1F;
    
    NSString *number = [self encodeAsNumber:left3];
    NSString *brandName = [self encodeAsBrandName:right5];
    
    return [NSString stringWithFormat:@"%@ %@ ", number, brandName];
}

- (NSString *)encodeAsNumber:(unsigned char)left3
{
    return [NSString stringWithFormat:@"%d", (left3 + 2)];
}

- (NSString *)encodeAsBrandName:(unsigned char)right5
{
    return [brandNames objectAtIndex:right5];
}

+ (NSData *)dataWithSpeakableString:(NSString *)s error:(NSError **)e
{
    NSMutableData *data = [NSMutableData new];
    
    NSUInteger endOfString = [s length];
    NSRange searchRange = NSMakeRange(0, endOfString);
    NSUInteger startOfSlice, endOfSlice;
    
    do {
        startOfSlice = [self positionOfNextDigitOnString:s range:searchRange];
        if (startOfSlice == NSNotFound) {
            if (e) {
                NSDictionary *userInfo = @{NSLocalizedDescriptionKey : @"Unable to parse"};
                *e = [NSError errorWithDomain:@"SpeakableBytes" code:1 userInfo:userInfo];
            }
            data = nil;
            break;
        }
        
        searchRange.location = startOfSlice + 1;
        searchRange.length = [[s substringFromIndex:searchRange.location] length];
        
        endOfSlice = [self positionOfNextDigitOnString:s range:searchRange];
        if (endOfSlice == NSNotFound) {
            endOfSlice = endOfString;
        }
        
        NSRange rangeOfSlice = NSMakeRange(startOfSlice, endOfSlice - startOfSlice);
        NSString *slice = [s substringWithRange:rangeOfSlice];
        NSData *decodedByte = [self byteFromSlice:slice];
        if (!decodedByte) {
            if (e) {
                NSDictionary *userInfo = @{NSLocalizedDescriptionKey : @"Unable to parse"};
                *e = [NSError errorWithDomain:@"SpeakableBytes" code:1 userInfo:userInfo];
            }
            data = nil;
            break;
        }
        [data appendData:decodedByte];
        
        searchRange.location = endOfSlice;
        searchRange.length = [[s substringFromIndex:searchRange.location] length];
    } while (endOfSlice != endOfString);
    
    return data;
}

+ (NSUInteger)positionOfNextDigitOnString:(NSString *)s range:(NSRange)searchRange
{
    NSCharacterSet *digits = [NSCharacterSet decimalDigitCharacterSet];
    NSRange digitRange = [s rangeOfCharacterFromSet:digits options:NSLiteralSearch range:searchRange];
    return digitRange.location;
}

+ (NSData *)byteFromSlice:(NSString *)s
{
    NSInteger number; NSString *brandName;
    [self getValuesForNumber:&number brandName:&brandName fromSlice:s];
    if (![self isNumberParseable:number] || ![self isBrandNameParseable:brandName]) {
        return nil;
    }
    unsigned char byte = [self byteFromNumber:number brandName:brandName];
    return [NSData dataWithByte:byte];
}

+ (void)getValuesForNumber:(NSInteger *)number brandName:(NSString **)brandName fromSlice:(NSString *)s
{
    NSString *sTrimmed = [s stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
    NSArray *sSliced = [sTrimmed componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
    sSliced = [sSliced filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"SELF != ''"]];
    
    *number = [[sSliced objectAtIndex:0] integerValue];
    *brandName = [sSliced objectAtIndex:1];
}

+ (BOOL)isNumberParseable:(NSInteger)number
{
    if (number < 2) {
        return NO;
    }
    return YES;
}

+ (BOOL)isBrandNameParseable:(NSString *)brandName
{
    if (![brandNames containsObject:brandName]) {
        return NO;
    }
    return YES;
}

+ (unsigned char)byteFromNumber:(NSInteger)number brandName:(NSString *)brandName
{
    unsigned char left3 = [self threeLeftmostBitsFrom:number];
    unsigned char right5 = [self fiveRightmostBitsFrom:brandName];
    unsigned char byte = [self byteByJoiningThreeLeftmostBits:left3 withFiveRightmostBits:right5];
    return byte;
}

+ (unsigned char)threeLeftmostBitsFrom:(NSInteger)number
{
    return number - 2;
}

+ (unsigned char)fiveRightmostBitsFrom:(NSString *)brandName
{
    return [brandNames indexOfObject:brandName];
}

+ (unsigned char)byteByJoiningThreeLeftmostBits:(unsigned char)left3 withFiveRightmostBits:(unsigned char)right5
{
    left3 = left3 << 5;
    return left3 | right5;
}

+ (NSData *)dataWithByte:(unsigned char)byte
{
    unsigned char buffer[] = { byte };
    return [NSData dataWithBytes:buffer length:1];
}

@end