Saving Array<NSValue> in CoreData as Transformable Attribute - ios

I have an app using CoreData with an entity that has a Transformable attribute.
The attribute is of type Array.
As these are compliant with NSCoding, I never had any problems saving this entity.
Today, I ran into an issue saving these entities which I never had a problem with in the past.
value for key 'NS.objects' was of unexpected class 'NSValue'
I don't know if a recent update broke this, but all of the sudden I cannot save my entity with the transformable attribute of type Array.
No idea where the problem came from. It has been working for a long time.
Why am I now getting an error trying to access an entity with a transformable attribute of type Array ?

If you just want to save an array of objects (like String), set Custom Class as [String].
You also can set values as [Data], and later get object with decoding it.

Related

Best way to save a dictionary containing bunch of Core Data objects?

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];

Realm inverse relationship returns object with nil properties

I got a class named Team, it has a RLMArray property called players with Player class objects.
When i try to access the team by calling (according to documentation)
[self linkingObjectsOfClass:#"Team" forProperty:#"players"];
on a player object, i get a single team object ( how it's supposed to be ), but all the properties are nil, even primary key.
Has anyone faced the same issue?
It's expected that instance variables of persisted RLMObject instances will be nil as the property getters read values directly from the Realm file. The instance variables are only used for objects prior to being saved to the Realm, and remain nil after that point.
The Debugging section of the Realm documentation touches on this topic and mentions an LLDB script that can be used to show property values of persisted objects when debugging in Xcode. The -description method on the model classes, used by NSLog when formatting objects using the %# format specifier, will also show the property values as expected.

RESTKit: Overwriting objects where the objectID is the same, but other attributes have changed.

When I GET the server, I check the attribute "objectID" on each object, and if the objectID is already in the local store, I don't store the object.
Question: What's the approach if the "objectID" exists, but its other attributes have changed and thus the entire object should be replaced with the new object? There is an other attribute called "lastModified" that will change. Do I compare against both "objectID" and "lastModified"?
Generally, yes, compare the id and then check the modified date. Try not to replace the object though, instead, pass the new object to the existing object and have it update itself (then throw away the new object).
Note that if you were using Core Data then RestKit could handle this for you using unique identifier (so it can find the existing objects and update them during the mapping process).

Add NSDictionary to NSManagedObject Category

I would like to add a NSDictionary into a NSManagedObject Category class (or the NSManagedObject class itself)
When I do this, and I try to access the property, an exception is thrown.
Is this actually possible? I can't add this property as transient in the model because there is no NSDictionary Data Type, of course.
Thanks!
You don't say how you have currently created the property or what the exception is, but from the description you give it sounds like you should be setting the attribute in the Core Data model to be transformable. Setting it to be transformable will cause the NSDictionary to be archived (and unarchived) as you use it using the standard NSCoding protocol. Be sure that everything you put into the dictionary supports the NSCoding protocol so that it is properly archived and restored.
Using transformable is the way. Below are few more insights on the transformable property.
The Transformable data type is a special data type that allows us to
create attributes based on an Objective-C class (custom objects). This
data type is heavily used for storing instances of UIImage, UIColor,
and so on. As the information stored in the persistent store has to be
in the form of NSData instance, while using Transformable data type,
we need to create Value Transformers to convert the custom object
(information in attribute of Transformable data type) into an instance
of NSData (before storing in the persistent store) and to convert the
instance of NSData back to custom object while retrieving from the
persistent store.

Why isnt BOOLEAN attribute of a Core Data entity__NSCFNumber and not __NSCFBoolean?

In Core Data Entities, we have to wrap primitive numbers (char,int,float,double and BOOL) to there Class cluster NSNumber.
Although the core data user interface let's us specify a type where I specifically mentio it as BOOLEAN and default type to YES or NO.
Now when I get a JSON-converted-NSDictionary from an API call I try to store a boolean true or false into this attribute.
However I have noticed, while printing the class of both the core data entity and the json-dictionary's corresponding value for the key in the debugger console, that
Core Data entity's NSNumber wrapped attributes class is __NSCFNumber and for the dictionary's value for the key is __NSCFBoolean.
I know about the class cluster pattern and I understand that we have subclasses under NSNumber whose actual objects are created when numberWithInt or numberWithBool are called and are represented as the one umbrella term NSNumber.
But what I did not understand was, why didnt the debugger show Core Data entities bool attribute as __NSCFBoolean ?

Resources