Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Problem with saving NSDate to the CoreData context

I'm trying to save managed object with one of the attribute's type Date to the managedObjectContext.

Code is like:

reminder.eventDate = selectedDate;
NSLog(@"Date: %@", selectedDate);
NSError *error = nil;
if (![reminder.managedObjectContext save:&error]) {
    NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
    abort();
}

during context saving program crashes with SIGABRT. Here is a console log:

2011-02-28 00:50:18.817 MyApp[9021:207] *** Terminating app due to uncaught 
exception 'NSInvalidArgumentException', reason: '-[__NSDate isEqualToString:]: 
unrecognized selector sent to instance 0x4e73490'
*** Call stack at first throw:
(
    0   CoreFoundation                      0x01057be9 __exceptionPreprocess + 185
    1   libobjc.A.dylib                     0x011ac5c2 objc_exception_throw + 47
    2   CoreFoundation                      0x010596fb -[NSObject(NSObject) doesNotRecognizeSelector:] + 187
    3   CoreFoundation                      0x00fc9366 ___forwarding___ + 966
    4   CoreFoundation                      0x00fc8f22 _CF_forwarding_prep_0 + 50

Does anyone knows why I have that? Second question is why when I check in debugger mode selectedDate isn't NSDate type but __NSDate (double underscore in front).

Thanks!

UPDATE:

I did some changes to easier catch the bug. so code now is like:

reminder.eventDate = [NSDate date];
NSLog(@"Date: %@", selectedDate);
NSError *error = nil;
if (![reminder.managedObjectContext save:&error]) {
    NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
    abort();
}

so, here we save definitely NSDate. reminder.eventDate is NSDate too. But I still have this error. If I comment reminder.eventDate = [NSDate date]; saving throws another error (date is mandatory field in NSData, so save: returns error "The operation couldn’t be completed." with eventDate = nil;. CoreData structure is checked multiple times - eventDate has Date type.

UPDATE (Problem solved): Finally I found the problem. eventDate was set as key for the detailTextLabel.text in my tableview cells (I used KVO for that). So if was no direct call and I wasn't able to find any method invokation for the eventDate. Strange thing is that crash was on the save method, not later. And in the call stack there is no tableView:cellForRowAtIndexPath: method at all...

like image 476
OgreSwamp Avatar asked Feb 27 '11 16:02

OgreSwamp


4 Answers

Silly as it sounds, I would suggest that you double check that both your reminder object and associated managedObjectContext are valid.

You are certain that your model correctly models eventDate as a date attribute, and you are also certain that the object you pass to the eventDate attribute is a NSDate object. So, try verifying that reminder and its managedObjectContext are not nil.

Finally, verify if all of the other attributes and relations are correctly set (check if you actually insert all of the required attributes and relations, check if the objects you use are of the correct type etc).

This will also help narrowing the possibilities.

EDIT: You can verifying what is actually happening inside your sqlite database. Simply add the following as an argument before starting your application:

-com.apple.CoreData.SQLDebug 1

see the documentation.

How you do this depends on your installed toolset (Xcode 3 or 4). I am using the latest Xcode 4 and to add an argument you simply select your current scheme, then you select Run "your app name" and click the Arguments tab to add the argument.

like image 99
Massimo Cafaro Avatar answered Nov 17 '22 13:11

Massimo Cafaro


That sounds like you have your data model set up to expect a string in the eventDate property, rather than a date.

like image 36
Simon Goldeen Avatar answered Nov 17 '22 13:11

Simon Goldeen


NSDate is a "class cluster", which means that instances you actually deal with will be instances of some private subclass of NSDate (in this case, __NSDate).

As for the error, I agree with Simon Goldeen that the most likely reason is that the data model or the NSManagedObject subclass is expecting a string rather than a date.

like image 25
Anomie Avatar answered Nov 17 '22 13:11

Anomie


Just to add to what has already been said:

It doesn't have to be a problem with the model or the NSManagedObject subclass. It could just be a piece of code almost anywhere that calls isEqualToString:. Somewhere you've got an object that the code assumes should be a NSString but is instead a NSDate object. I would look at any code that might convert dates to strings.

However, since it happens upon save I would look at any customizations you might have done to the subclass.

The place to start is by searching the project for isEqualToString:.

Update:

Since isEqualToString is a testing method it can be activated anytime you do a compare for a string such as in a sort. I couldn't reproduce your exact error but the following code does something similar:

id idDate=[NSDate date];
NSString *bob=[NSString stringWithString:@"bob"];
NSString *steve=@"test this";
steve=idDate;
NSLog(@"test=%@",([steve compare:bob]) ?@"YES":@"NO");

... complies but throws an exception:

-[NSCFString timeIntervalSinceReferenceDate]: unrecognized selector sent to instance 0x4040

So, you can see how these types of errors can slip in. It's also a demonstration for why you should be careful with the use of id.

like image 2
TechZen Avatar answered Nov 17 '22 12:11

TechZen