JSONModel with MagicalRecord - ios

MagicalRecord is a nice library to manage coredata.In my application I have to processes json from web service for managing Json we are using JSONModel. Now the problem is I have to use two separate class to manage magical record and jsonModel.
Is there any way by which I can combine these two?
Thanks in Advance.

What I personally do is to add to all my JSONModel instances a method called:
-(id)mergeWithContext:
Whenever I get a JSON object from the web, JSONModel parses it for me and converts the data to what I need, then if I want to save it to CoreData I just call mergeWithContext: and pass the current context to it.
The further in my mergeWithContext: method I just create a new entity matching the current JSONModel object and copy over all values. (I actually also check whether an entity with the model's ID already exists in CoreData - then I update it, otherwise I create a new instance).
Not too difficult and you get a fair amount of flexibility if you need to add some custom behaviour when the data is saved.
mergeWithContext: returns of course the entity itself, so I can work with it further if I need to.

Related

Understanding of NSCoreData and MSManagedObject subclasses

I am learning a bit on NSCoreData and before introducing it some existing projects I have, I would like to validate my good understanding of the core principles.
From what I have understood, NSCoreData make it easier to manage local storage of object (+retrieval after that) by subclassing our Model class from NSManagedObject rather than from NSObject.
Right ?
I have a few questions then. Let's consider I am building a real estate application with as core model object the class Property that can represent an appartment, a house, and all related information. Currently it is managed in my app as a subclass of NSObject.
1) I retrieve the properties from the server through a search query, and have written a initWithJson : method to populate each instance.
Now if I subclass Property from NSManagedObject, I will create my instances by using
+(id)insertNewObjectForEntityForName:(NSString *)entityName
inManagedObjectContext:(NSManagedObjectContext *)context
and I will be still be able to add a populateWithJson: to my class to fill in the properties.
Then I will create a lot of Property instances in the current managedObjectContext, and if I do a save, they will be stored at the physical layer.
If I call again the same webservice, and retrieve the same JSON content, I will recreate the identical managed objects.
How to avoid redundancy with the [managedObjectContext save:&error] call and not to store physically several time the representation of a single real life property ?
2) Let's say I want to store physically only some properties, for instance only the one the user want to have as favorites.
[managedObjectContext save:&error] will save all created / modified / deleted managed objects from the context to the physical layer, and not only the one I want.
How to achieve that ?
Am I supposed to declare another context (managedObjectContext2), move the instance I want to store in that context, and do the save in that one ?
(I mean, I will have a context just to manipulate the object, create instances from the JSON and represents them in UI ... and a second one to actually do the storage)
Or am I supposed to stores all the objects, and add a isFavorite BOOL property , and then fetching using a predicate on that property ?
3) The app has a common navigation pattern : the UITableView lists Properties instance with the minimum information required, and going on a detail view call a webservice to request more information on a specific Property instance (images, full text description).
Is it a good practice for instance to call the webservice only if the property.fullDescription is nil, and then update the object and store it locally with all detailed information, and the next time only to fetch it locally with a predicate on the property.id ?
What about object that might be updated server-side after they have been created?
Thanks for your lights
1) Retrieve the server data into a temporary form (array of dictionaries?), then for each possible property in the array, check to see if you already have an object in Core Data that matches. If you do, either ignore it or update any changed attributes; if not, create a Property object.
2) Decide which things you want to persist in order to support your app's functions. There's no point in creating a managed object for something you don't want to save. Note, though, that Core Data supports sub-classes if you want both Property and FavoriteProperty.
3) Entirely up to your "business rules"…. How often do you need local data to be updated? The only technical consideration might be the guideline to not keep large files locally that can be re-created on demand.

How to use NSManaged object class using NSObject class

I have NSObject class name TrackInfo which contains tracks info like name , artist name,thumb image etc.
I use this class as downloading data and save information to that class after parsing data.
Now I have another tab in which, I have to show some data. This is same kind of data like trackInfo. But when app is in OFFLINE, I have to make NSManagedObject. It is same as trackinfo.
Can I use NSObject class instead of NSManagedObject or Vice-Versa ?
What I basically wants to do is, I have to display track info from one class either Trackinfo (NSObject class) or NSManagedObjectClass which is used to save data when app is in offline.
Short answer is yes, you can. How? You can find a useful discussion Organising Core Data for iOS.
The long answer can be grabbed within the documentation.
NSManagedObject is a generic class that implements all the basic
behavior required of a Core Data model object. It is not possible to
use instances of direct subclasses of NSObject (or any other class not
inheriting from NSManagedObject) with a managed object context. You
may create custom subclasses of NSManagedObject, although this is not
always required. If no custom logic is needed, a complete object graph
can be formed with NSManagedObject instances.
A managed object is associated with an entity description (an instance
of NSEntityDescription) that provides metadata about the object
(including the name of the entity that the object represents and the
names of its attributes and relationships) and with a managed object
context that tracks changes to the object graph. 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:).
About your question, it depends on what you need to achieve. If your goal is to perform a sync mechanism between your device and the server, you should set up 1) a model with a TrackInfo entity 2) a Core Data stack that relies on a persistent store like SQLite. Then you should modify TrackInfo to take into account modifications to that entity. For example, a dirty flag property (0 or 1) or a timestamp. When you do a modification on your TrackInfo you update that property. When the connection is restored you need to query against that property and sync with the server. If you choose the timestamp, the server should say what is the latest timestamp to query against.

What's the simplest way to encode a chosen 'root' Core Data entity together with all of its relationships?

I use Core Data within my iOS 7 app to handle the editing and creation of entities. The entities have relationships between them, which all have inverses (as Apple advises).
For the sake of this question, let's pick any one of these interrelated entities and call it the Root entity: the thing that I want to encode with; the thing that logically lives on the 'top' of the hierarchy. I will call this the 'object graph'.
The question is:
What's the easiest way of encoding and decoding such an object graph to and from NSData?
The reason I want to do this is that I'd like my Core Data object graph to be persisted onto a cloud service, without the need of writing my own NSIncrementalStore subclass (it's a bit involved...!).
AutoCoding together with HRCoder almost looks like it could do the job, but I've experimented with this combination and it doesn't quite work with NSManagedObjects at the time of writing.
Still, I'm seeking alternatives. There can't only be one way to do this, surely.
It doesn't have to be JSON, but it'd be nice. Binary would be fine.
It seems to me you do not need to subclass NSIncrementalStore. You can create records and save them to your store with a plain vanilla store created via addPersistentStoreWithType:... with a NSPersistentStoreCoordinator.
The straight-forward way is to handle the incoming JSON by simply taking the data and copying it to the properties of your NSManagedObject subclasses, like this:
object.title = jsonDictionary[#"title"];
object.numericAttribute = [jsonDictionary[#"numericAttribute] integerValue];
If you take care about naming the attribute and entity names exactly the same you can maybe use some shortcuts using KVC, like
[object setValue:jsonDictionary[key] forKey:key];
I once did the above for a large legacy project where it was not feasible to repeat the old attribute names, so I used a custom property list (plist) to match around 800 attribute names.

best data persistance for NSObject subclass

I'm fairly new to iOS development, so I need some advise.
I'm working on a project (creating a character sheet app for an upcoming table top RPG), and I seem to have put the cart a bit before the horse.
I've already created a subclass of NSObject called characterClass that holds everything I need for a single instance of the character sheet. It also has methods to calculate derived information. I have 2 more classes storing abilities, and have them in NSArrays in the characterClass. Now that it's working, I need to work on data persistance, and storing/retrieving multiple characters.
I'm thinking, of using Core Data, creating a separate entity that matches my characterClass, and having a characterClass init method that pulls the data out of Core Data and puts it into the current instance of characterClass. That seems a bit obtuse to me, (implementing a class separate from the entity) but maybe it's a good way to do it.
I would eventually like to set up dropbox syncing for this information, so whatever I do I would like to have compatible with that. (Core Data with XML files as the backend?)
What would be the best method for something like this?
Rather than just pull the data out of Core Data and use it to create your character class, you could just tweak your character class so that it is an NSManagedObject subclass. That way you are storing your objects directly in Core Data

Save an existing Model to a CoreData DB

I'm learning Core Data and I understand all the examples for creating a brand-new object, assigning values and saving it to the managedContext (insertNewObjectForEntityForName).
However, what if I've already created an object elsewhere (model Category)? In this case I'd want to just assign the current Context to this Model, and then save it.
What is the command/approach to take an in-memory Model, and then assign to a context so it can be saved?
If you want to use Core Data to manage your data, you'll need to:
create an appropriate model description (.xcdatamodeld file)
modify your model class(es) so that they inherit from NSManagedObject
set the "Class" for each entity in your model description to one of your NSManagedObject subclasses
add code to your app to create and manage the Core Data stack, fetch data, etc.
This is all very do-able, but I wouldn't recommend that you attempt it until you have a solid understanding of Core Data and your reasons for adopting it in your project. The lack of clarity in your question may indicate that you're not quite there yet; you might benefit from working on a small project that uses Core Data from the start.
If all you want to do is to save your data, you should know that Core Data is not the only way to do that. A much simpler approach to saving your data would be to adopt the NSCoding protocol in your data model and then use a NSKeyedArchiver to store your data. Get the full story from the Archives and Serializations Programming Guide. There are other ways to do it as well, but NSKeyedArchiver is a good place to start.
You can only save NSManagedObjects (and their subclasses) to CoreData. NSManagesObject can not be created except in the context of an NSManagedObjectContext.
So, what you're saying is confusing. Do you have a non-CoreData model object?

Resources