Using Objective-C blocks to log Core Data entities

Posted by on Nov 17, 2010 in code | No Comments

Usually when I want to log the Core Data entities returned by a query in a particular context, I just passed the object to a log statement, like so:

NSLog(@"Query returned %@", theCoreDataObject);

This works OK when you just have one object to log, but if you want to log the whole array of entities, it gets ugly:

“<MyEntity: 0x4d8d680> (entity: MyEntity; id: 0x4d760a0 <x-coredata://8D01CA08-1D17-4536-844E-EFFDC8539074/MyEntity/p869459> ; data: <fault>)”,
“<MyEntity: 0x4d708b0> (entity: MyEntity; id: 0x4d66e10 <x-coredata://8D01CA08-1D17-4536-844E-EFFDC8539074/MyEntity/p869460> ; data: <fault>)”,
“<MyEntity: 0x4d78a70> (entity: MyEntity; id: 0x4d8c030 <x-coredata://8D01CA08-1D17-4536-844E-EFFDC8539074/MyEntity/p869461> ; data: <fault>)”,
“<MyEntity: 0x4d7ba90> (entity: MyEntity; id: 0x4d03af0 <x-coredata://8D01CA08-1D17-4536-844E-EFFDC8539074/MyEntity/p869462> ; data: <fault>)”,
“<MyEntity: 0x4d7bae0> (entity: MyEntity; id: 0x4d0c660 <x-coredata://8D01CA08-1D17-4536-844E-EFFDC8539074/MyEntity/p869463> ; data: <fault>)”,
“<MyEntity: 0x4d7bc80> (entity: MyEntity; id: 0x4d76900 <x-coredata://8D01CA08-1D17-4536-844E-EFFDC8539074/MyEntity/p869464> ; data: <fault>)”

What am I supposed to do with that, particularly when the data has faulted? If it didn’t fault, the output is even more verbose. I could do something like this to just get the data I’m interested in:

for (id theCoreDataObject in results) {
   NSLog(@"Query returned %@ (%.1f)",
                  [theCoreDataObject someField],
                  [[theCoreDataObject someOtherField] floatValue]]);

But who wants multi-line log statements littering their code? Since I’m trying to log the same type of array in a few different places, a closure (or block, in Objective-C terms) seemed like a perfect solution. Here’s the block definition:

NSString* (^formatMyEntity)(NSArray *) = ^(NSArray *entities) {
    NSMutableArray *output = [NSMutableArray arrayWithCapacity:[entities count]];
    for (id entity in entities) {
        [output addObject:[NSString stringWithFormat:@"%@ (%.1f)",
                          [entity someField], [[entity someOtherField] floatValue]]];
    return [output componentsJoinedByString:@", "];

To use it, I can just call the block formatMyEntity() like a function:

NSLog(@"Query returned %@", formatMyEntity(results));

And the output is much nicer:

Query returned: for (4), place (4), in (2), price (2), value (2), with (2)

Leave a Reply