8

I would like to cast dynamically in Objective C and access instance properties. Here a pseudo code:

id obj; if (condition1) obj = (Class1*)[_fetchedResults objectAtIndex:indexPath.row]; else obj = (Class2*)[_fetchedResults objectAtIndex:indexPath.row]; NSNumber *latitude = obj.latitude; 

Then the compiler tells me the following: property 'latitude' not found on object of type '__strong id'

Either Class1 and Class2 are core data entities and have nearly the same kind of attributes. In condition1 _fetchedResults returns objects of type Class1 and in condition2 _fetchedResults returns objects of type Class2.

Could someone give me a hint how to solve this kind of problem?

Thanks!

1
  • I think you should make sure firstly that what [_fetchedResults objectAtIndex:indexPath.row] returns is the Class has the latitude property. Also, casting a none NSManagedObject type to a NSManagedObject type is wrong either. You need a NSManagedObjectContext whenever and however you create a NSManagedObject instance. Commented Aug 7, 2014 at 7:48

2 Answers 2

7

You can access the properties through Key-Value Coding (KVC):

[obj valueForKey:@"latitude"] 
Sign up to request clarification or add additional context in comments.

5 Comments

Note that using KVC to do this robs you of any type-checking from the compiler.
@ipmcc Sure, but so does using id in the first place :-)
@Monolo This is unnecessary and has the same effect as [obj latitude]
@hooleyhoop True. I'd venture that using KVC conveys intention slightly better, but that is a matter of coding style. The error messages you'd get (at runtime, alas) are also quite different. And you might in theory have defined a getter with a different name if we want to cover that one, too.
Key-Value coding is documented practice for managed objects, so the only thing I would change is to replace id by NSManagedObject *.
3

The obj variable needs to be of a type that has the property in question. If both entities have the same property, one way to achieve this would be for the property to be declared on a common base class. If it's not appropriate for these two types to share a common base class, then you could have them adopt a common protocol, like this:

@protocol LatitudeHaving @property (copy) NSNumber* latitude; @end @interface Class1 (AdoptLatitudeHaving) <LatitudeHaving> @end @interface Class2 (AdoptLatitudeHaving) <LatitudeHaving> @end 

From there, you would declare obj as being an id<LatitutdeHaving>, like this:

id<LatitudeHaving> obj; if (condition1) obj = (Class1*)[_fetchedResults objectAtIndex:indexPath.row]; else obj = (Class2*)[_fetchedResults objectAtIndex:indexPath.row]; NSNumber *latitude = obj.latitude; 

And that should do it. FWIW, protocols are similar to Interfaces in Java.

2 Comments

what are the Class1* and Class2* casts for?
objectAtIndex: returns an id not an id<LatitudeHaving>. Those casts may not be strictly necessary to avoid compiler complaints, but I was trying to make the code as close to the OP's code as possible.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.