我有一个简单的 UIViewTable,通过故事板中的 UINavigationController push segue 实现了深入细节。有时会发生表视图控制器似乎被释放的情况,而我在详细视图中,因此我得到了著名的:
[MyViewController controllerWillChangeContent:]: message sent to deallocated instance
我解释得更好,我有一个 NSOperation 队列,它异步加载我的数据,并在完成后立即填充表。正确检索数据并填充表格。对于详细视图,我单击一个单元格并将 NSManagedObjectID 传递给 prepareForSegue 方法中的目标控制器。当我对详细视图进行更改时,非常随机地,获取的控制器松开了它的委托,或者看起来,作为控制器的委托本身被释放了。导致崩溃。
获取的结果控制器被声明为一个属性:
@property(nonatomic,strong) NSFetchedResultsController *fetchedResultsController;
然后这就是从 viewDidLoad 开始的一切工作方式。
- (void)viewDidLoad {
[super viewDidLoad];
[self loadDataAsynchronously];
}
-(void)loadDataAsynchronously {
NSOperationQueue *queue = [NSOperationQueue new];
NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self
selector:@selector(loadData)
object:nil];
[queue addOperation:operation];
}
-(void)loadData {
NSFetchRequest *findAllEntities = [[NSFetchRequest alloc] init];
[findAllEntities setEntity:ENTITY_DESC];
NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:@"created" ascending:YES];
[findAllEntities setSortDescriptors:[NSArray arrayWithObject:sort]];
[findAllEntities setFetchBatchSize:20];
[NSFetchedResultsController deleteCacheWithName:@"MyCache"];
if(self.fetchedResultsController==nil) {
self.fetchedResultsController = [[NSFetchedResultsController alloc]
initWithFetchRequest:findAllPlants
managedObjectContext:MOC
sectionNameKeyPath:nil
cacheName:@"MyCache"];
self.fetchedResultsController.delegate=self;
}
NSError *error=nil;
if (![FRC performFetch:&error]) {
exit(EXIT_FAILURE);
}
[self.dataTableView performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:YES];
}
这段代码可以工作,而且大多数时候也可以在细节视图中工作,这被称为像这样的 segue:
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
IP2SegueIdentifier segueIdentifier = [IP2Factory segueSolver:[segue identifier]];
MyDestinationViewController *dvc = [segue destinationViewController];
NSIndexPath *indexPath = [TV indexPathForSelectedRow];
dvc.entityID=[[self.fetchedResultsController objectAtIndexPath: indexPath] objectID];
}
并且目标控制器通过询问上下文正确获取实体ID并重建对象。然后,当我在细节视图控制器中时,我可以对实体进行更改,当我返回导航层次结构时,我会保存上下文。正是在这一点上,应用程序崩溃了,就在上下文保存时。不是那么频繁,而是时不时。因为获取的结果控制器识别更改并提交给已被释放的委托。
在这一点上我几乎没有疑问,我使用的是 iOS 5 和 ARC,所以编译器应该(几乎)完全控制 release 和 dealloc 方法。而且我还使用了一个带有简单导航层次结构的故事板,它应该保证整个以前的视图控制器链得到保留。
我还运行分析器进行内存泄漏/僵尸分析,但无法发现任何错误,相反我很高兴所有对象管理都很好。
在这一点上我没有太多猜测,所以请随时指出我可能忘记检查的东西,或者你在我的代码中看到的错误。
谢谢