I know it's not recommended to save NSMutableArray to Core Data but I need to access the array on another view controller (using one of the segue methods (such as passing a variable to another view controller) won't do the job).
So unless there's another way that I'm not aware of, how can I save the array to core data?
I'm using Swift.
I think your question is not how to save NSMutableArray to Core Data, instead, your question seems like is How to access data on another viewController?
First, I think you can get some knowledge about Delegate.
Second,Here is a Q&A I can share with you which I think may help you to figure out your confused.Passing Data between View Controllers
Saving NSArray to Core Data is possible via Transformable-type attributes.
Saving NSMutableArray is not possible. Only immutable ones.
if you want to save a mutable array to core data, use copy method. It will return immutable copy of your mutable object.
Related
This question is poorly phased but this can be better explained in code.
We have a Core Data Stack with private and main contexts as defined by Marcus Zarra here: http://martiancraft.com/blog/2015/03/core-data-stack/
We call a separate class to do a fetch request (main context) and return an array of NSManagedObjects:
NSArray *ourManagedObjects = [[Client sharedClient].coreDataManager fetchArrayForClass:[OurObject class] sortKey:#"name" ascending:YES];
We then do some processing and store a reference:
self.ourObjects = processedManagedObjects
Our view contains a UITableView and this data is used to populate it and that works just fine.
We change the data on our CMS, pull to refresh on the UITableView to trigger a sync (private context) and then call this same function to retrieve the updated data. However, the fetch request returns the exact same data as before even though when I check the sqlite db directly it contains the new data. To get the new values to display I have to reload the app.
I have discovered that if I don't assign the processedManagedObjects to self, the fetch request does indeed return the correct data, so it looks like holding a reference to the NSManagedObject stops it from getting new data from the main context. However I have no idea why that would be.
To clarify, we're pretty sure there's nothing wrong with our Core Data Stack, even when these managed objects are not being updated, other are being updated just fine, it's only this one where we store a local reference.
It sounds like what's going on is:
Managed objects don't automatically update themselves to reflect the latest data in the persistent store when changes are made via a different managed object context.
As a result, if you keep a reference to the objects, they keep whatever data they already had.
On the other hand if you don't keep a reference but instead re-fetch them, you get the new data because there was no managed object hanging around with its old data.
You have a few options:
You could keep the reference and have your context refresh the managed objects, using either the refresh(_, mergeChanges:) method or refreshAllObjects().
If it makes sense for your app, use an NSFetchedResultsController and use its delegate methods to be notified of changes.
Don't keep the reference.
The first is probably best-- refreshAllObjects() is probably what you want. Other options might be better based on other details of your app.
Try setting the shouldRefreshRefetchedObjects property of the fetch request to true. According to the documentation:
By default when you fetch objects, they maintain their current property values, even if the values in the persistent store have changed. Invoking this method with the parameter true means that when the fetch is executed, the property values of fetched objects are updated with the current values in the persistent store.
I wish to save a dictionary containing some Core Data objects (bunch of different entities). The objects also have quite a few relationships (and inverse relationships) defined. What would be the best way to go about it?
I tried using NSKeyedArchiver and writing to a file. While that works great, when trying to read from the file using NSKeyedUnarchiver, it fails on one of the classes with the error
-[SomeEntity initWithCoder:]: unrecognized selector sent to instance
EDIT - More details
I have a bunch of objects, each having properties based on which they can be filtered. The properties are in themselves Core Data entity objects since they have a complex structure.
I wish to save the filters the user has selected so that the next time they view the objects, the objects can be filtered as per their previous selection.
Say there are 3 filters, Filter A, B and C and each can have 5 different values. Now the user might select Filter A1, A2, B1 and C3 (or a different combination). My question, how do I save these selected filters (A1, A2, B1 and C3 in this case) using Core Data?
Let me see if I understand your question: You have a collection of managedObjects that are already saved in a context. They may already be persisted in the SQL database. You want to save that collection ALSO to another file for other purposes. You have already considered saving the information of this collection inside core-data in some way and have already rejected it. You have also considered simply saving the query generation tokens to save the state of the database as it currently is, but that also is not what you want. The point is to have a file that contains a copy of some of the managedObjects organized in a way that you can get the data back without using the SQL database that was already designed exactly for that purpose.
Solution 1: Turn each managed object in a dictionary.
You can get every attribute and every property of every object by getting a managed object's entity and then accessing the attributesByName and
relationshipsByName property of the entity. From there you make a simple loop to put each property into a dictionary. I also suggest you store the objectID and point to the objectID when encoding the relationships. Then replace the managedObject in your dictionary with dictionary that contains all the attributes and relationship. This new dictionary should be easy to archive and unarchive.
This make sure that the data when you unarchive is exactly how you left it. When you unarchive you will get a COPY of data and if the managed objects have changed in your database since then, you will get the OLD values. Also these copies are not core-data object because they are unconnected to a managed Object Context.
Solution 2: Just save the Managed Object's ObjectId.
Replace every managed object in your collection with the object's objectId. This dictionary can be easily archived. When you unarchive it replace every objectId with a core data object (if found) using existingObjectWithID: on the context. If entities have been deleted then you won't get them back. If entities have changed then you will get the NEW values.
Solution 3: Don't do any of this
It seems to me that you may not be aware core-data are already saved in a database. If you have some collection of managedObjects, you should be able to recreated it from your database. If you aren't able to, then you should add properties and/or relationships that will allow you to so.
Try like this :
ARCHIVE :
NSDictionary *yourDictData = [NSDictionary dictionaryWithObject:json forKey:#"key"]; // This is for example. Here you have to replace ur dictionary
NSData *myData = [NSKeyedArchiver archivedDataWithRootObject:yourDictData];
UNARCHIVE :
NSDictionary *myData = [NSKeyedUnarchiver unarchiveObjectWithData:yourDictData];
I have a question about creating a database with core data.
In my app at first start I should parse some json to obtain some data to insert in core data db.
my json files are structured in this way: (I show only an element of my json)
[{"id":"s1",
"n":"Name hotel",
"id_loc":["l1","l2","l3","l4"],
"val":3,
"tel1":"12345678",
"tel2":"12345678",
"obj":
{"id":"o1",
"n":"Name",
"des":"description",
"flag":"red"}
}]
I understand that I can consider this as an entity in coredata and consider all element as attribute, it's clear.
Now you can see that inside my json there is an array "id_loc" and an object (or dictionary) "obj".
In core data what's the way to manage these two elements?
I suppose that "obj" can be managed as a new entity, and "id_loc", what's the way to set it in my core data DB?
Can you help me?
Thanks
For obj, it's as you suggest: create a new entity, and set up a relationship between the two entities.
For id_loc it depends on how you need to use the data.
If you just want to have that data available when you look up an instance (that is, you maybe display this data but don't ned to search for it), you can store the strings in an NSArray. Make the attribute transformable in the Core Data model editor, and Core Data will read/write the complete array.
If you need to look up data based on id_loc values (for example: Find every object where id_loc contains l3), the best approach is to create another entity to hold values of id_loc, and set up a to-many relationship to that new entity.
I hope this question isn't too general/ambiguous...
I'm writing an iphone quiz game app and am having trouble figuring out the best way to handle data. Currently I am thinking of having a single Model class that holds an array of "User" classes which each have an array of user-specific "Question" classes. I'd like to be able to access the overarching Model from any of my view controllers, but that means I'll probably have to pass the model object to any new view controller, use a singleton, or do something else. What is the best way to access my Model object from other classes? Another factor I'm not sure about is being able to save the data - would I have to use Core Data/SQLite to save my single Model object, or is there a simpler way?
I'd start by designing a schema using CoreData. IMO, its best to start out using CoreData because then you'll never have to convert your data layer to CoreData, in the event that your app scales beyond a simple object or two.
The other route would be to create a web service that returns your data... so you just call the service and it returns a collection of user objects. You can either send down the entire object graph with the questions, or create another service to return a collection of questions for a specific user. If you have a web server handy, this method scales the best because you don't have to rely on app updates to get new questions into your system. I would still use CoreData to cache the results... so that way you're not downloading the same information all the time.
So when it comes to accessing CoreData objects, I use a repository class that's a singleton. This makes it easy for any view controller to grab an instance of the repository and get some data. Here's what something like that might look like;
[[Repository defaultRepository] findFirst:[User class]
where:#"name == 'John'"]
There's a lot of redundant code to fetch data so wrapping that up in an object will help get all that nasty code, like predicates and sorting, out of your view controllers. You can see where I leverage a va_list in the where clause so I can inject that string right into my predicate. Here are some other methods you could implement:
- (NSArray *) findAll:(Class)entity
sortByKey:(NSString *)key
ascending:(BOOL)ascending;
- (NSArray *) findAll:(Class)entity
sortByKey:(NSString *)key
ascending:(BOOL)ascending
where:(NSString *)format, ...;
- (id) findFirst:(Class)entity
where:(NSString *)format, ...;
I'm not sure if this is the preferred way, but I've had a lot of success with this method. Hope this helps!
Check this link, this will help you a lot
Link: http://mobile.tutsplus.com/tutorials/iphone/iphone-sdk_store-data/
This cover 4 major ways to store data in iPhone with sample code.
1) NSUserDeafult
2) Property Lists
3) SQLLite
4) Core Data
I have a question about NSKeyedUnarchiver, NSMutableArray and self-created classes. The data is stored by NSKeyedArchiver to user defaults. When the data load into the user defaults will be printed to the console of the data stream. I want to unpack the data into an array, the array will be empty.
Maybe someone of you knows how I save the array or the array load.
Thank you.
Greetings,
Schumi
You should go through this documentation first. But basically, To enable archiving on custom class objects you will have to adopt the NSCoding protocol and implement initWithCoder: and encodeWithCoder: methods.