Add existing objects to Core Data? - iphone

I couldn't find anything about this topic. I have NSManagedObjects that I don't use insertNewObject... I use alloc init, and then add them to array sort them alphabetically, and then I want to add them to entities and save the context. Any ideas on how to add them to entities, without making entirely new objects?

This may be more proper as a comment, but it is, in fact, the answer.
Do not do that. First, read the documentation, then use the API as directed.
Directly from the documentation for NSManagedObject:
It is important that a managed object is properly configured for use
with Core Data. If you instantiate a managed object directly, you must
call the designated initializer
(initWithEntity:insertIntoManagedObjectContext:).
Then, from the documentation for initWithEntity:insertIntoManagedObjectContext:
Important This method is the designated initializer for
NSManagedObject. You must not initialize a managed object simply by
sending it init.
Note, that the above statement is actually highlighted in an attention-getting box in the documentation.

Related

CoreDataGeneratedAccessor method giving "unrecognized selector sent to instance" error

When i call the method:
- (void)removeObjectFromMediaAtIndex:(NSUInteger)idx;
which is one of the default methods in a file created as a core data object, i'm getting an error of unrecognized selector sent to instance. Anybody know why this might be happening?
Ensure that your NSManagedObject sublcass instance was created using an NSManagedObjectContext and not directly. Instead of leveraging #synthesize for properties, NSManagedObject sublcasses leverage the #dynamic keyword which indicates the accessors will be created at runtime - in this case, by the NSManagedObjectContext. They will not be there if you create the object instance using something like alloc]init];
It is a notorious Core Data bug. It is almost 2-year old but sadly it is still there. See this post: Exception thrown in NSOrderedSet generated accessors.
It sounds like you may have altered your data model without altering the classes, or vice-versa. Or perhaps one of your team members did (my team quickly learned about this danger). Another possibility is that the reference you are using is not actually the class you think it is. Sometimes if you overrelease an object, another object will occupy the previous memory space but it will not be the correct class.
However, this doesn't look like a default method. The default methods I am used to seeing are add object, remove object, change to a new NSSet, and one more that I can't quite remember off the top of my head. However, if you got the CoreData object to use an NSArray instead it would make sense.

Reflection in Objective-C (iPhone)

I want to populate [MyClass class] from a JSON string.
I use json-framework to get the NSDictionary, and it's dead easy to instantiate and setValue: forKey:... on my data object.
But for more complex data objects with classes as members of MyClass,
ie:
MyOtherClass *classNoTwo
I tried with
Class test = object_getClass(myClass.classNoTwo);
id foo = [[test alloc] init];
But foo is nil/null. The only way I found to get around it is to in my init method of MyClass is to alloc memory for it, and later replace it.
I would also like to know how to get rid of the myClass.classNoTo reference, as I am not supposed to know all the properties in my general parser.
Please don't just tell me to read the documentation, because I've done that, and I can't figure it out.
Thanks in advance
Try calling class_getProperty() to access a property of a particular name and then property_getAttributes() on the property returned by the first function. This will return a string that encodes the property's attributes, including the type. The format of the string is explained in Property Type Strings in the documentation.
Finally, when you have derived the type of the property, use NSClassFromString() to instantiate an object.
Also see the docs for the two functions mentioned for more details.
I have written a very simple dependency injection container called Factory. I do not get your question entirely, but the problems we solve look similar. Take a look at my sources, they are very simple and should get you started. You might be interested especially in the ClassAnalyzer class. It’s just a hack, but you should be able to get what you want from there.

Couldn't I just pass an copied string to an Core Data property?

The docs say:
The default implementation does not
copy attribute values. If the
attribute value may be mutable and
implements the NSCopying protocol (as
is the case with NSString, for
example), you can copy the value in a
custom accessor to help preserve
encapsulation (for example, in the
case where an instance of
NSMutableString is passed as a value).
So instead of getting into trouble and inconvenience with overwriting accessors in my NSManagedObject subclass, couldn't I simply do something like this?
myManagedObject.firstName = [[firstNameMutableStr copy] autorelease];
This would have the exact same effect, or not? The dynamic implementation would retain that anyways ... so.... why not the easy way?
It's an open question whether having to remember to copy the mutable string every where in code you set the attribute is "the easy way."
With a custom accessor, you just write the copy once then forget about. It copies automatically from that point on.
Just imagine that in thousands of lines of code you forgot to copy just once and developed a subtle bug because that one attribute of the managed object sporadically changed because some other totally unrelated code subsequently changed the mutable string you held only by reference.
I could tell you some stories of weekends lost to debugging because someone took "the easy way."

What's the fastest and easiest way to create a new managed object?

When I have a subclass of NSManagedObject, I could do this:
Friend *newFriend = (Friend*)[[NSManagedObject alloc] initWithEntity:#"Friend"
insertIntoManagedObjectContext:moc];
But since I have a subclass, couldn't I simply instantiate it another way so that I don't have to tell it what Entity it is? (I mean: Is there already an predefined initializer for this, or must I write my own?)
Besides initWithEntity:insertIntoManagedObjectContext: the only two methods you can use to customize object initialization are awakeFromInsert and awakeFromFetch. See the full discussion related to Core Data object initialization here.

MVC, can model save/load its data?

Quick question, my data model is a singleton object and it contains a list of names that I want to archive. My idea is to make the model responsible for loading and saving it's own data. The model's load method will be called by the ViewController's viewDidLoad method and save by the ViewController's applicationWillTerminate. I could do the load/save directly within the ViewController, but this would be messy as the list of names are an instance variable of the model.
gary
You could just load and save in the init and dealloc methods (although it's common to call a save method explicitly). It's a good idea to encapsulate it within the model class. If you're loading from the network you might want to have a separate loadData method or something, rather than doing it from init.
Apple recommends using lazy initialization wherever possible, so I think you're heading down the right path, though you might want to consider making the method name something that looks like a property accessor, e.g. -names rather than -load (especially since there's a class method named +load that means something quite different).