1

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?

user3539959
  • 383
  • 3
  • 15
  • The class that its failing must be a custom class made by you. This means you have to implement these 2 methods initWithCoder: and encodeWithCoder: to properly archive and unarchive them. Once you implemented them you should stop getting that error. – Pochi Jul 13 '17 at 05:17
  • @Pochi in that case, why does archiving go through alright? Shouldn't that fail as well? – user3539959 Jul 13 '17 at 05:25

2 Answers2

1

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.

Jon Rose
  • 8,373
  • 1
  • 30
  • 36
  • Thanks, that pretty much sums up what I need. Yes, I do have the data in the core data db. The problem here is the dictionary has a collection of different entity objects - so it has SomeEntity1, SomeEntity2... And at times it might have just one object of SomeEntity1 and 3 of SomeEntity2. It is built dynamically. TBH I don't know how I should save these into CoreData due to this dynamic nature. If you can help me there, I'd be grateful! – user3539959 Jul 13 '17 at 06:49
  • It is hard to advices without details. – Jon Rose Jul 13 '17 at 06:59
  • I have edited the question, in case it helps. Thanks. – user3539959 Jul 13 '17 at 09:26
  • After reading the details it is clear the option 3 is correct. Saving it as a dictionary will save out of date information. Saving objectIDs will not show new data that enters that filter. If you want to save the last selected filter values then just save the last selected filter values. Save the info in userDefaults. It is small and there is no reason to complicate your core-data model for it. It is was userDefaults is made for. – Jon Rose Jul 13 '17 at 11:32
0

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];
Soumya Ranjan
  • 4,817
  • 2
  • 26
  • 51