Search code examples
objective-coopclasscore-dataobjc-protocol

Casting down with Objective C


Say I have a subclass of NSManagedObject called MBManagedSquare and MBManagedCircle. An MBManagedSquare and MBManagedCircle define a method prepareFromDictionary:(NSDictionary*)dic, and both of their implementations are different.

Say I have this code:

NSString *type = // could be @"MBManagedSquare" or @"MBManagedCircle"
NSEntityDescription *desc = [NSEntityDescription entityForName:type inManagedObjectContext:_context];
NSManagedObject *object = [[NSManagedObject alloc] initWithEntity:desc insertIntoManagedObjectContext:_context];

So the type of entity it will be with Core Data is determined dynamically via a type string. So all I know is that it is an NSManagedObject.

What I want to do is call the prepareFromDictionary: method for the right class.

So if the type is "MBManagedSquare", I want to cast the object to an MBManagedSquare, and then call

[castedObject prepareFromDictionary:dic];

What I tried doing is:

Class class = NSClassFromString(type);
class *castedObject = (class*)object;

but I get an expected expression error. I'm not sure if this is even possible. How would I do this?


Solution

  • You don't need to worry about calling the right class if the selectors and their parameters match -- ObjC has plenty of dynamic dispatch powers.

    As far as an implementation, it's pretty common to either:

    • create a common base with the interface you want
    • or create a protocol which both classes adopt:

    MONProtocol.h

    @protocol MONManagedShapeProtocol < NSObject >
    - (void)prepareFromDictionary:(NSDictionary *)pDictionary;
    @end
    

    then (since you know it is one of the two types, MBManagedSquare or MBManagedCircle) either derive from the base or adopt the protocol and declare your variable like:

    // if subclass
    MBManagedShape * castedObject = (MBManagedShape*)object;
    

    or

    // if protocol
    NSManagedObject<MONManagedShapeProtocol>* castedObject =
                            (NSManagedObject <MONManagedShapeProtocol>*)object;