1

I am using BTLE to write data into one of the characteristics of peripheral. I wanted to send an NSDictionary into that characteristics. Since there is a limitation of 130 bytes of data being sent over BTLE, I want an efficient way of compressing NSDictionary into NSData and then send across. I am using below piece of code which is exceeding limit. Any ideas?

NSDictionary *aDict = @{ @"Value1": @"sadsadasdasdsadqwwqsadasd",
                         @"Value2": @"10",
                         @"Value3": @"12" };
NSData *aData = [NSKeyedArchiver archivedDataWithRootObject:aDict];
NSLog(@"Data Size = %@",
        [NSByteCountFormatter stringFromByteCount:aData.length
                                       countStyle:NSByteCountFormatterCountStyleFile]);
Greg
  • 9,068
  • 6
  • 49
  • 91
Abhinav
  • 37,684
  • 43
  • 191
  • 309
  • Check this out. It should help. http://stackoverflow.com/questions/3157356/converting-nsdictionary-object-to-nsdata-object-and-vice-versa – Abdullah Shafique Jul 14 '13 at 01:39
  • You could try to compress the NSData as described here: http://stackoverflow.com/a/234099/475052 – Carl Veazey Jul 14 '13 at 01:47
  • Don't know what representation NSKeyedArchiver uses -- probably JSON would be more compact. In any event, there's not likely to be much "gas" in the representation, so you'll have to resort to data compression of some sort if you really want to squeeze things together. – Hot Licks Jul 14 '13 at 02:15
  • 5
    (Plain old JSON would represent the above in about 65 bytes -- essentially the same length as your initialization statement, minus all the `@` characters.) – Hot Licks Jul 14 '13 at 02:18

1 Answers1

6

I don't think trying to use any form of compression will be effective, or even an improvement at all at this scale, because all compression algorithms work best when they have a lot of data to work with, and hence many duplicates and patterns to find. When your entire data size is 130 bytes, any form of zip compression isn't really a viable option.


If your dictionary will only contain property-list values (arrays, dictionaries, strings, numbers), then you can use JSON serialisation instead of NSKeyedArchiver:

NSData *JSONData = [NSJSONSerialization dataWithJSONObject:anObject
                                                   options:0
                                                     error:nil];

This immediately makes the output data much shorter in your case:

NSDictionary *aDict = @{ @"Value1": @"sadsadasdasdsadqwwqsadasd",
                         @"Value2": @"10",
                         @"Value3": @"12" };

NSData *aData = [NSKeyedArchiver archivedDataWithRootObject:aDict];
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:aDict
                                                   options:0
                                                     error:nil];

NSLog(@"NSKeyedArchiver Data Size = %@, JSON Data Size = %@",
      [NSByteCountFormatter stringFromByteCount:aData.length
                                     countStyle:NSByteCountFormatterCountStyleFile],
      [NSByteCountFormatter stringFromByteCount:jsonData.length
                                     countStyle:NSByteCountFormatterCountStyleFile]
      );

NSKeyedArchiver Data Size = 380 bytes, JSON Data Size = 66 bytes

As you can see, the JSON serialised data is almost 6 times smaller than the NSKeyedArchiver serialised data, and fits easily in your 130 byte limit. And the best thing is, it's only one line of code.

UPDATE: Just to rub it in some more :), here is the data that NSKeyedArchiver produces (added as image because it contains a lot of "illegal" characters that I couldn't copy and paste):

NSKeyedArchiver Data

As you can see, it contains a lot of useless data that you don't really need (highlighted blue), that's basically just to give NSKeyedUnarchiver enough information to be able to unarchive it later.

Now, let's look at the JSON data:

{"Value3":"12","Value2":"10","Value1":"sadsadasdasdsadqwwqsadasd"}

That's it. One line. 66 bytes. Of those, 19 bytes aren't your values. In other words, 71% of that JSON data is your values, and the rest is markup, so to speak. Meanwhile, in the NSKeyedArchiver data, your values make up, wait for it, 12% of the result. I think you can clearly see which one is more efficient for storage here.

Greg
  • 9,068
  • 6
  • 49
  • 91