Search code examples
iosobjective-cnsmutablearraynsarraynsdictionary

containsObject is returning NO after the app is restarted


I have a UITabelView displaying a list of items(returned from the server), users will be able to select any item and add it to his own section. Upon selecting an item, I am retrieving the selected item details and saving it to a pList file, the list will then be displaying a small icon informing the user that the item is added to his section. User will be able to remove it from his section by tapping the icon again.

To know if the item is already in his section, i am using

[self.myItemsArray containsObject:item]

Everything is working perfect if the user don't exit the application. The issue is occurring once the app is restarted. When I retrieve the tableview list from the database or from server, all the items will not be shown as on my list and [self.myItemsArray containsObject:item] will return NO for the previous added items.

I was searching for an alternative way, by creating an NSArray of my items id's and will then check if the new array will contains the item id to display the icon. the new issue is that the id is returned as double from the server and stored as it is. The application is crashing when creating the array:

[self.myItemsArray valueForKey:@"Id"]

myItemsArray is an array of items(item is an NSDictionary containing all the details)

So i am desperate now,could anyone help me by resolving any of the above issues? I prefer the first one, since containsObject will be more simple, but I don't mind to solve it with the second choice if the first will not work.


Solution

  • You'll need to make sure you have a good isEqual: method defined for your custom class, since that's what NSArray uses to determine containment: https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSArray_Class/#//apple_ref/occ/instm/NSArray/containsObject:

    Let's say this class has something like a 'key' or 'id' value that is unique for each instance of the class (which in your case is a double type). This will not always be the case, of course; it's often an aggregate of individual properties/ivars that constitutes a unique 'key', but for the purposes of this discussion let's say that such a field exists. Your code might look something like this (all in the .m):

    static double const EPSILON = .000000001; // You'll need to be the judge of how "close" values can be to each other but still be distinct
    
    @interface MyObjectClass: NSObject
    @property (nonatomic, readonly) double uniqueKey;
    @end
    
    @implementation MyObjectClass
    
    // ...
    
    - (BOOL)isEqual:(id)object
    {
        if (self == object) { return YES; }
        if (!object isKindOfClass:[MyObjectClass class]]) { return NO; }
    
        MyObjectClass *myObject = (MyObjectClass *)object;
        if (abs(self.uniqueKey - myObject.uniqueKey) < EPSILON) { return YES; }
        return NO;
    }
    
    //...
    
    @end
    

    Note that you should NOT check for direct equality between two float or double values; see How dangerous is it to compare floating point values? for a good discussion about the pitfalls of working with floating point and double precision values.