How to best check if the contents of two objects are identical? - ios

I have an array of cached objects that I retrieve using NSCoding and NSKeyedUnarchiver. These have have many properties.
I now need to check if the contents of an object I create is identical to any of the cached objects contents in the array.
I of course cannot check if the references to the objects are equal using containsObject, but I can check if their contents are identical. I know how to achieve the end result, but what's best practice in this case? I would want it to take as little time as possible.
And keep in mind that the objects are only identical if all their properties match.
Thank you for your time!

Implement the isEqual: and hash methods on the class. The implementation of isEqual: should compare all properties.
Once you have those two methods properly implemented you can make use of collection methods such as NSArray containsObject: or NSArray indexOfObjects:, etc.

Related

NSMutable array containsObject, does it check the contents of the object or the object type?

I am a little confused to how containsObject works. Does it check to see if it contains an instance of an object type or does it compare the inside of the objects variables etc to see if they match?
This is an implementation detail, you can work on the basis that it calls isEqual: on each items and works on the result of that.
Under the hood it's probably calling hash on each item and comparing that, then, if the hash matches it will call isEqual: to make sure it's a real match.

get all tables (classes) from realm

I'm using Realm.io as database and I need a select * from all_tables in Realm.
I mean a method returning an RLMArray, but I have not found anything about this.
I need the class reference, such as Realm Browser.
Thanks.
You can use [realm.schema.objectSchema valueForKey:#"className"] to get an NSArray of all of the RLMObject subclasses used in the Realm.
I don't believe this is possible at the moment. You should request it on github. In the mean time you will have to create your own. First you have to know that an RLMArray can only hold one type so if in these different tables there are different types than you can not do the following. It would be as easy as creating your own method for this. It would consist of getting all objects from each table and just inserting them into the RLMArray; If your tables don't have the same type then you will have to use a NSMutableArray or an NSArray.

Serializing a custom object into NSDictionary or NSArray to use NSJSONSerialization

I've been looking for a way to serialize custom objects with NSJSONSerialization avoiding the use of third-party libraries, and I couldn't find any example. Is there any way of "automatically" create an NSDictionary and NSArray from an object, without having to create it typing in code all the object's member names yourself one by one and setting manually the values? I found a related post, but it is pretty old, things may have now changed.
Thanks
You can use KVC to ask any object for dictionaryWithValuesForKeys: which will give you a dictionary representation of the object.
If you need to change the property / key names then you want to do some mapping and (depending on what you're using the JSON for) you may find RestKit useful.

How to override hash and isEqual for NSManagedObjects?

We have a bunch of NSManagedObjects of various types.
Some of them have members that are NSSet's of other NSManagedObjects.
The problem is that I really need to override the hash and isEquals methods of the objects that are IN the set - but they are NSManagedObjects.
I'm having problems with getting multiple identical objects in the set.
As far as I can tell, since hash defaults to the object address - all objects are different. So I need to override hash and isEquals - but can't see any way to do it.
What we have is a bunch of stuff in the System, and more comes in via XML - sometimes repeats of the existing objects. When they are the same, I don't want dups added to the set.
As mentioned above by Wain, NSManagedObject documentation states that you must not override hash or isEqual:. So this means a stock NSSet does not do what you need.
Some of your options are:
Enumerate the NSSet contents to identify and remove duplicates
Write a factory method for your NSManagedObjects that will return the same object when given the same inputs
Fix the XML to not include duplicated objects
Unique the objects coming from the XML before they become NSManagedObjects
Modify the input XML to include a unique identifier that you can track, assuming the duplicated objects are exact duplicates
Implement your own NSSet-like collection class that performs a different uniquing test than hash and isEqual:

iOS: Archiving NSMutableArray

I've Googled and searched SO for this with no straightforward results. It seems I have a fundamental misunderstanding of the following from Apple's documentation:
An archive can store an arbitrarily complex object graph. The archive
preserves the identity of every object in the graph and all the
relationships it has with all the other objects in the graph. When
unarchived, the rebuilt object graph should, with few exceptions, be
an exact copy of the original object graph.
Assume that I have an NSMutableArray that is a collection of Person objects. Each Person object implements initWithCoder and encodeWithCoder. Further, any given Person may have an NSMutableArray of objects (similarly coding-compliant) of Task.
My understanding is that there is a way to archive, thus triggering a cascading serialization of arbitrary depth, depending on implementation of the coding protocol. So in my view controller, I have a willEnterBackground that does:
data = [NSKeyedArchiver archivedDataWithRootObject:self.people];
// persist to NSUserDefaults
and I have a viewDidLoad that does:
// read from NSUserDefaults
self.people = [NSKeyedUnarchiver unarchiveObjectWithData:data];
This all happens, but two things:
The initWithCoder and encodeWithCoder in the objects contained by the people array are never called.
Unsurprisingly, the result is that self.people is an NSMutableArray of size 0. Surprisingly, the data that is unarchived is 252 bytes long, which looks about right.
Suggestions? Hints?
Even though you implemented those 2 methods, did you declare your Person class to be in the protocol ?

Resources