[NSNull isEqualToString]

时间:2010-10-14 14:53:25

标签: iphone objective-c

由于运行时将isEqualToString:发送到NSNull对象,我的程序崩溃了。我无法找到这个NSNull的来源;我从未明确创建过一个。我也找不到任何调用isEqualToString的人或者是什么。

我的理解是NSNull是一个被反对使用,只是为了解决你不能将nil添加到集合的事实。我的程序确实创建了几个自动释放阵列;所以我猜他们中的一个是以某种方式结束了NSNull。奇怪的是,这些数组中没有一个应该包含任何NSString对象,这意味着isEqualToString:如果它被发送到我的数组中的对象,会导致崩溃。

我正在使用CoreData获取请求和谓词创建这些数组:

 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];

后来我进一步过滤了fetchedResults,如下所示:

    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"];

什么可能导致NSNull最终进入其中一个阵列?在创建数组之后查看它们,我没有看到任何NSNull对象。还有什么可能导致NSNull被创建,特别是在系统期待NSString的地方创建吗?无论如何使用调试器来追踪isEqualToString:消息实际发送的位置? (如果我正在逐步执行,它会在我的所有代码执行后发生,我的猜测是某些事情正在自动释放的地方)。

谢谢!

2 个答案:

答案 0 :(得分:1)

好了几乎整整2天没有做任何事情,只是想弄清楚这次崩溃,我找到了它。

原来它与我的阵列无关!我有一个被观察的物体,观察者在观察物被解除分配之前没有停止观察。我不知道的是,当一个观察对象被解除分配时,它会通知其观察者它的值正在被更新。具体来说,他们正在更新为NSNull。

所以我的Client.name属性正在更新为NSNull,它提醒我的观察者它正在被更改。在我的observeValueForKeyPath:方法中,我试图将UILabel的文本更新为新的客户端名称,这导致了崩溃。

真正令人烦恼的是,我已经不得不跳过一堆篮球,以确保当我的观察者被解除分配时,它停止观察它正在观察的任何东西。现在我必须进去做更多花哨的东西,以确保在我的客户端被解除分配之前,任何观察它的东西都会停止观察它。相当痛苦。

但它已经修好了!

答案 1 :(得分:0)

我不习惯使用CoreData获取请求但是当我解析JSON时,如果对象已损坏或者它不是正确的JSON,则对象的ID是NSNULL,所以可能在创建时出错了数组和系统返回一个NSNull值而不是正确的NSArray,当它试图寻找valueForKey时,它获取NSNull isEqualToString调用