views:

54

answers:

2

I have a class that contains multiple user objects and as such has an array of them as an instance variable:

NSMutableArray *users;

The tricky part is setting it. I am deserializing these objects from a server via Objective Resource, and for backend reasons users can only be returned as a long string of UIDs - what I have locally is a separate dictionary of users keyed to UIDs. Given the string uidString of comma separated UIDs I override the default setter and populate the actual user objects:

@dynamic users;
- (void)setUsers:(id)uidString {
   users = [NSMutableArray arrayWithArray:
                 [[User allUsersDictionary] objectsForKeys:[(NSString*)uidString componentsSeparatedByString:@","]]];
}

The problem is this: I now serialize these to database using SQLitePO, which stores these as the array of user objects, not the original string. So when I retrieve it from database the setter mistakenly treats this array of user objects as a string! Where I actually want to adjust the setter's behavior when it gets this object from DB vs. over the network.

I can't just make the getter serialize back into a string without tearing up large code that reference this array of user objects, and I tried to detect in the setter whether I have a string or an array coming in:

if ([uidString respondsToSelector:@selector(addObject)]) {
        // Already an array, so don't do anything - just assign users = uidString

but no success... so I'm kind of stuck - any suggestions? Thanks in advance!

+2  A: 

Hello ambertech,

The solution you've tried is not exactly wrong, but should look like this:

if ([uidString respondsToSelector:@selector(addObject:)]) {
    // Already an array, so don't do anything - just assign users = uidString

Seems that you've forggoten about the ":" - the addObject takes one parameter after all.

However, the proper way to do is to check the class of passed object:

if ([uidString isKindOfClass[NSArray class]])

Hope this was helpful,

Cheers, Pawel

Pawel
Thanks Pawel - it works now using your second suggestion. For your second suggestion I had originally tried (in noob fashion) if([uidString class] == [NSString class]) not realizing "isKindOfClass" is the correct way
ambertch
+1  A: 

It would be much less confusing - and more in line with the usual Cocoa style - if you let the actual setter take an NSArray or an NSMutableArray:

- (void)setUsers:(NSArray*)usersArray { ... }

... and have another method, say -setUsersFromUidString:, taking an NSString parameter, for the first case:

- (void)setUsersFromUidString:(NSString*)uidString { ... }

Your original approach loses the advantage of self-documentation Objective-C has and will confuse users of the class.

Georg Fritzsche
Thanks for the style tip, I will keep this in mind!
ambertch