0

I have a custom object containing several NSString objects, some ints and a few bools. I am using NSKeyedArchiver to archive a copy of the object into an NSData object.

The user than makes changes to the object variables, which are connected to an IB interface.

After the changes are made, the new version of the object is archived into a second NSData object.

These two objects are compared using

[myNSData1 isEqualToData: myNSData2];

In most cases it works perfectly well, but there is one very troubling situation:

Let's say the object had a variable initialized as follows:

NSString *myString = @"";

After the object was archived into myNSData1, we called the following:

myString = [myNSTextField stringValue];

Logging myString to the console reveals that the value of myString is still

@""

and thus has not changed value.

We now archive the object into myNSData2.

Upon executing the comparison statement above, however, it now returns FALSE. It ONLY returns FALSE if the original assignment of @"" is replaced with the @"" contained in the textfield using stringValue.

Why is this?

Greg Steiner
  • 647
  • 1
  • 9
  • 20

1 Answers1

1

Have a look at the types of those strings (NSLog([myString className]) should work), because NSString is a class cluster. I'm guessing that you'll find that and one of those strings is an NSCFString, and the other is an NSCFConstantString. The archiver encodes type information, so if the types are different, the NSData will also be different.

I wouldn't rely on the NSData objects being identical. If you want to compare the two, you'd be better off unarchiving them and using isEqual:. That way, you'd have full control.

Tom Dalling
  • 23,305
  • 6
  • 62
  • 80
  • Excellent point. That would be the missing piece of information I'm sure. If I use the isEqual, would I have to check each var or can you apply that to the custom objects themselves? – Greg Steiner May 23 '12 at 03:40
  • Found a nice article explaining the "gotchas", which it looks like caught me: http://www.cocoanetics.com/2012/03/beware-of-nsstring-optimizations/ – Greg Steiner May 23 '12 at 03:49
  • You implement `isEqual:` on your custom objects, and then you generally check each ivar against the other object like `if(![someIvar isEqual:other->someIvar]) return false;`, but really you can do whatever you want in there. – Tom Dalling May 23 '12 at 07:23
  • Tom, looks like the string differences aren't the problem. I checked and the strings are NFCSConstantStrings both BEFORE and AFTER the change. So in BOTH cases, we have an NSCFConstantString of @""... and yet, the NSData objects are showing they are not equal. Any other ideas what might be different? – Greg Steiner May 23 '12 at 17:40
  • Ignore the above comment.. (It won't let me edit anymore) This comment supersedes the previous one. :) I've tried comparing the two strings using several different methods and here's what I've come up with: The variable I will call String1. The other is a string contained in an NSTextField is the sender... Both are NSCFConstantString class. Both are set to @"" Both have a length of 0. [string1 isEqual: [sender stringValue]] shows that they are equal. And yet, when archiving them, this one variable is causing the two NSData objects to be Not Equal. I'm very confused... ugh. – Greg Steiner May 23 '12 at 18:05
  • I've given up on this...lol I broke down and just wrote a custom method to compare each and every ivar in my object. I would still love to know why this is happening though, so if anyone knows or has any ideas, please let me know! :D – Greg Steiner May 24 '12 at 03:42