Since I posted many ways of not doing it, i wanted to share my solution as well.
I admit, it is not catching lots of possible errors. At least I may help someone avoid typing in the brand names 
Here is NSData+Speakable.m
[code]#import “NSData+Speakable.h”
@implementation NSData (Speakable)
static NSDictionary *brandValuesDictionary;
void initbrandValues()
{
brandValuesDictionary = @{@“Camry”:@0,
@“Nikon”:@1,
@“Apple”:@2,
@“Ford”:@3,
@“Audi”:@4,
@“Google”:@5,
@“Nike”:@6,
@“Amazon”:@7,
@“Honda”:@8,
@“Mazda”:@9,
@“Buick”:@10,
@“Fiat”:@11,
@“Jeep”:@12,
@“Lexus”:@13,
@“Volvo”:@14,
@“Fuji”:@15,
@“Sony”:@16,
@“Delta”:@17,
@“Focus”:@18,
@“Puma”:@19,
@“Samsung”:@20,
@“Tivo”:@21,
@“Halo”:@22,
@“Sting”:@23,
@“Shrek”:@24,
@“Avatar”:@25,
@“Shell”:@26,
@“Visa”:@27,
@“Vogue”:@28,
@“Twitter”:@29,
@“Lego”:@30,
@“Pepsi”:@31
};
}
/*
leftmost 3 bits will be encoded as digits between 2 and 9
Attention: explicitly declared singleByte as unsigned.
Otherwise the right shift operator treats the leftmost bit as a sign!
*/
NSString *encodeByte(unsigned int singleByte)
{
NSArray *brandNamesArray = [brandValuesDictionary keysSortedByValueUsingSelector:@selector(compare:)];
unsigned int threeLeftmostBits = singleByte >> 5;
threeLeftmostBits+=2;
// rightmost 5 bits will be encoded as strings
unsigned int fiveRightmostBits = singleByte & 31; // AND 00011111
NSString *result = [NSString stringWithFormat:@"%d %@ ", threeLeftmostBits, brandNamesArray[fiveRightmostBits]];
return(result);
}
- (NSString *)encodeAsSpeakableString
{
NSMutableString *result = [[NSMutableString alloc]init];
initbrandValues();
unsigned char *byteBuffer = (unsigned char *)[self bytes];
for (char b=0; b<8; b++)
{
[result appendString:encodeByte(byteBuffer[b])];
}
return result;
}
/*
takes the coded values and decodes them to its original HEX Value
eg. lm=5 rm=@“Fuji” returns 6f
*/
unsigned char decodeByte(unsigned int lm, NSString *rm, NSError **e) {
unsigned int result = 0;
// get the correct leftmost bits
result +=(lm-2);
result = result << 5;
// get the rightmost bits NSInteger
int rmbits = [brandValuesDictionary[rm] intValue];
if (!rmbits) {
if (e) {
NSDictionary *userInfo = @{NSLocalizedDescriptionKey: @“Unable to parse”};
*e = [NSError errorWithDomain:@“Speakable Bytes” code:1 userInfo];
return 0;
}
}
result = result | rmbits; // bitwise-OR
return result;
}
-
(NSData *)dataWithSpeakableString:(NSString *)s
error:(NSError **)e
{
NSMutableData *resultData = [[NSMutableData alloc]init];
unsigned char *aBuffer;
initbrandValues();
// Build an Array of substrings
NSArray *wordGroups = [s componentsSeparatedByString:@" "];
// Loop through array. If element is number then - together with the following element - decode them to byte
for(int i=0; i<[wordGroups count]; i++) {
unsigned int testInt = (unsigned int)[wordGroups[i] intValue];
if (testInt) {
unsigned int encodedLeftmostBits = (unsigned int)testInt;
NSString *encodedRightmostBits = wordGroups[i+1];
unsigned char byteToAppend = decodeByte(encodedLeftmostBits, encodedRightmostBits, e);
if (byteToAppend) {
// To add the byte to NSMutableArray the method appendByte is called. It needs a buffer instead of the byte itself
// So, first a pointer to the byte is formed
aBuffer = &byteToAppend;
[resultData appendBytes:aBuffer length:1];
} else {
return nil;
}
}
}
return resultData;
}
@end
[/code]