views:

92

answers:

2

My program is crashing as a result of the runtime sending isEqualToString: to a NSNull object. I cannot find where this NSNull is coming from; I never explicitly create one. I also can't find at all who or what is calling isEqualToString.

My understanding is that NSNull is an objected used only to get around the fact that you cannot add nil to a collection. My program does create several auto-release arrays; so I am guessing one of them is somehow ending up with an NSNull in it. The odd part is that none of these arrays are supposed to contain any NSString objects, which means that isEqualToString: would cause a crash if it were sent to an object in my array anyway.

I am creating these arrays with CoreData fetch requests and predicates:

 NSFetchRequest *request = [[NSFetchRequest alloc] init];
 NSPredicate *predicate = [NSPredicate predicateWithFormat:@"property.name CONTAINS[cd] %@ OR client.name CONTAINS[cd] %@", self.searchDisplayController.searchBar.text, self.searchDisplayController.searchBar.text];
 request.entity = [NSEntityDescription entityForName:@"SearchIndex" inManagedObjectContext:appDelegate.rootViewController.managedObjectContext];
 request.predicate = predicate;
 [request setFetchLimit:0];

 NSSortDescriptor *sortDescriptor1 = [[NSSortDescriptor alloc] initWithKey:@"client" ascending:YES];
 NSSortDescriptor *sortDescriptor2 = [[NSSortDescriptor alloc] initWithKey:@"property" ascending:YES];
 NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor1, sortDescriptor2, nil];
 request.sortDescriptors = sortDescriptors;
 [sortDescriptors release];
 [sortDescriptor1 release];
 [sortDescriptor2 release];
 NSError *error = nil;

 NSFetchedResultsController *controller = [[NSFetchedResultsController alloc] initWithFetchRequest:request managedObjectContext:appDelegate.managedObjectContext sectionNameKeyPath:@"client" cacheName:nil];
 self.resultsController = controller;
 [controller release];

 [self.resultsController performFetch:&error];

 [request release];

Later I further filter the fetchedResults like this:

    id <NSFetchedResultsSectionInfo> sectionInfo = [self.resultsController.sections objectAtIndex:section];

 NSPredicate *predicate = [NSPredicate predicateWithFormat:@"property.name CONTAINS[cd] %@", self.searchDisplayController.searchBar.text];
 NSArray *array = [sectionInfo.objects filteredArrayUsingPredicate:predicate];

 return [array valueForKey:@"property"];

What could cause an NSNull to end up in one of these arrays? Looking at the arrays after they are created, I don't see any NSNull objects. Is there anything else that could cause an NSNull to get created, specifically to get created in a place where the system is expecting an NSString instead? Is there anyway to use the debugger to track down where the isEqualToString: message is actually being sent? (If I'm stepping through, it happens after all my code is executed, my guess was somewhere where things are being autoreleased).

Thanks!

A: 

im not used to work with CoreData fetch requests but when I was parsing a JSON, if the object was corrupted or it was not a proper JSON, the id of the object was NSNULL, so probably you are making something wrong when creating the array and the system is returning you an NSNull value instead of a correct NSArray, and when it tries to look for the valueForKey, its getting that NSNull isEqualToString call

JonLOo
I just now deleted all my existing data and started fresh with just 2 test entries; and I still have the same problem. So it doesn't seem to be related to any particular piece of data.
GendoIkari
+1  A: 

Well after almost 2 full days of doing nothing but trying to figure out this crash, I found it.

Turns out it had nothing to do with my arrays! I had an object that was being observed, and the observer didn't stop observing before the observed object was dealloced. What I didn't know is that when an observe object gets dealloced, it notifies its observers that its values are being updated. Specifically, that they are being updated to NSNull.

So my Client.name property was being updated to NSNull, which alerted my observer that it was being changed. In my observeValueForKeyPath: method, I was trying to update a UILabel's text to the new Client name, and this was causing the crash.

What's really annoying is that I had already had to jump through a bunch of hoops to make sure that when my observer was being dealloced, it stopped observing anything it was observing. Now I had to go in and do a bunch more fancy stuff to ensure that before my Client gets dealloced, anything observing it stops observing it. Quite the pain.

But it's fixed!

GendoIkari