Reputation: 1879
I have an issue where I am getting in an object of type id. i know its base type is an NSManagedObject but the custom attributes for whatever type it actually is (name, email, etc) are what i really need. in the long run, i am trying to make one method that will turn my custom NSManagedObjects into NSDictionaries. maybe i am going down the wrong path in general but....
If i have something like
-(void)someMethod:(id)obj{
...
Class someClass = NSClassFromString([[obj class] description]);
...
i can get the class from that but then i cannot really figure out how to cast my object as that class.
ideally this would be the next few lines of that code
someClass* myObject = (someClass*)obj;
NSArray *keys = [[[myObject entity] attributesByName] allKeys];
NSDictionary *dict = [myObject dictionaryWithValuesForKeys:keys];
//do something with dict
...
but i cannot figure out how to get an object of the type someClass. I have seen where you can use the NSClassFromString object for an alloc init call like
id someObject = [[className alloc] init];
but that will not work for this situation as i already have an object passed in that I need. any ideas / criticisms? I am really trying to avoid a crap load of if statements for all of my items but it may be the quickest way right now...
Upvotes: 3
Views: 4352
Reputation: 47699
You can, of course, use object_getClassName to get the char*
name of the class.
Upvotes: 1
Reputation: 8357
If your sole goal is to convert an object (id
) into a dictionary. Since you stated that you know they are all instances of NSManagedObject
, you can safely cast it:
- (void)someMethod:(id)object {
NSManagedObject* managedObject = (NSManagedObject *)object;
Actually, if you want to be curt about it, this could be changed to:
- (void)someMethod:(NSManagedObject *)managedObject {
if you're declaring the method.
You can access the meta data about a managed object by accessing its entity:
NSEntityDescription *entity = [managedObject entity];
From there, get a description of each property:
NSDictionary *descriptions = [entity propertiesByName];
This dictionary will have all the keys you want in your dictionary, and an NSAttributeDescription
or an NSRelationshipDescription
as the value.
The fact that you have written custom classes to provide functionality on these classes is irrelevant! You can access all the data in them regardless of whether they are NSManagedObject
instances, or subclasses thereof.
Upvotes: 1
Reputation: 119242
If they are all NSManagedObject subclasses, and all you will be calling on them is valueForKey or other methods that are implemented by NSManagedObject, just cast to NSManagedObject. If I'm missing something, please let me know.
In answer to your comment on the original question - you already have this in your sample:
NSDictionary *myObjectDictionary = [[myObject entity] attributesByName];
This gives you a dictionary containing all the attributes of your managed object, with the attribute name as the key in each case. You then use these keys to call valueForKey on your object.
Perhaps a point I need to make is that it is fine to cast an object as its superclass, if you are not going to call any subclass specific methods on it.
Upvotes: 3
Reputation: 5999
Strictly speaking, I don't think you can cast an object in Obj-C, but you can cast the pointer to another class (that's probably what you mean, Sorry to be nit-picky).
I'm not sure offhand how to handle the casting in a programmatically smart way, but if you have a reasonable number of classes you can just use conditional blocks to handle the different cases:
if ([obj isMemberOfClass:[MyClass class]]) {
...
} else if ([obj isMemberOfClass:[MyOtherClass class]]) {
...
}
If the code in each of these blocks is largely (or even partially) the same, you can always add a superclass between NSManagedObject and your classes that contains the common code, so you can start by casting the pointer to that superclass, handle the common stuff, and still dive into conditionals if necessary.
I'm sure someone else will swoop in with a smarter answer, but there are my thoughts. Goof luck!
Upvotes: 0
Reputation: 52728
The question is a little confusing, but are you looking for the isKindOfClass:
method?
From the NSObject
Reference:
NSMutableData *myData = [NSMutableData dataWithCapacity:30];
id anArchiver = [[NSArchiver alloc] initForWritingWithMutableData:myData];
if ( [anArchiver isKindOfClass:[NSCoder class]] )
...
Also, you are casting properly. This is the correct way to cast an object to type MyClass
:
MyClass *myObject = (MyClass *)obj;
If nothing here has helped can you show the errors you are getting or what exactly is not working?
Upvotes: 0