(BTW: do you remember my previous post about Groovy: 21 things I like and don't like about Groovy? - there is an example of Groovy expando mechanism)
I know and use Objective-C categories. I use them to, for example, re-implement methods that are already provided.
But only yesterday, while writing some iPhone piece of code using SBJSON library I realised that in fact Objective-C category mechanism is the same as Groovy expando mechanism.
SBJSON example
For example SBJSON adds
But I (with a help of categories of course!) went one step farther :) I used Apple Runtime library to dynamically scan for all properties in given object, create dictionary and then create JSON string in one step.
Enhanced JSONRepresentation method
I pointed my browser to Mac OS X Reference Library - Objective-C Runtime Reference.
Based on the reference I changed the original
Nice :)
Cheers,
Łukasz
For example SBJSON adds
JSONRepresentation method to NSObject. But in fact it only works for dictionaries and arrays so you have to invoke it this way:User *user = [User new]; user.emai = @"lukasz@example.com"; user.password = @"super_secret"; NSDictionary *userDictionary = [user dictionaryWithValuesForKeys:[NSArray arrayWithObjects:@"email",@"password",nil]]; NSString *userDictionary = [person JSONRepresentation];
But I (with a help of categories of course!) went one step farther :) I used Apple Runtime library to dynamically scan for all properties in given object, create dictionary and then create JSON string in one step.
Enhanced JSONRepresentation method
I pointed my browser to Mac OS X Reference Library - Objective-C Runtime Reference.
Based on the reference I changed the original
JSONRepresentation implementation (located in NSObject+SBJSON.m file) to this:#import <Foundation/NSObjCRuntime.h>
#import <objc/objc.h>
#import <objc/runtime.h>
- (NSString *)JSONRepresentation {
SBJsonWriter *jsonWriter = [SBJsonWriter new];
NSString *json = nil;
if ([self isKindOfClass:[NSDictionary class]] || [self isKindOfClass:[NSArray class]]) {
json = [jsonWriter stringWithObject:self];
} else {
NSUInteger propertyCount = 0;
objc_property_t* properties = class_copyPropertyList([self class], &propertyCount);
NSMutableArray *keys = [NSMutableArray new];
for (NSUInteger i = 0; i < propertyCount; i++) {
objc_property_t property = *(properties + i);
[keys addObject:[NSString stringWithCString:property_getName(property) encoding:NSASCIIStringEncoding]];
}
free(properties);
NSDictionary *dictionary = [self dictionaryWithValuesForKeys:keys];
json = [jsonWriter stringWithObject:dictionary];
}
if (!json)
NSLog(@"-JSONRepresentation failed. Error trace is: %@", [jsonWriter errorTrace]);
[jsonWriter release];
return json;
Works like a charm :) Now instead of explicitly creating NSDictionary all you have to do is: [user JSONRepresentation];
Nice :)
Cheers,
Łukasz

0 comments:
Post a Comment