Leo*_*rdo 4 memory-leaks objective-c nsfetchedresultscontroller ios5 uistoryboard
我有一个简单的UIViewTable,在故事板中使用UINavigationController push segue实现了深入细节.它不时发生,表视图控制器似乎被解除分配,而我在详细视图中,因此我得到了着名的:
[MyViewController controllerWillChangeContent:]: message sent to deallocated instance
Run Code Online (Sandbox Code Playgroud)
我解释得更好,我有一个NSOperation队列,它异步加载我的数据,并在它刚刚完成时填充表.正确检索数据并填充表格.对于详细视图,我在prepareForSegue方法中单击一个单元格并将NSManagedObjectID传递给目标控制器.当我对详细信息视图进行更改时,非常随机,取出的控制器松开其委托,或者看起来,作为控制器的委托本身被取消分配.导致崩溃.
获取的结果控制器声明为属性:
@property(nonatomic,strong) NSFetchedResultsController *fetchedResultsController;
Run Code Online (Sandbox Code Playgroud)
然后这就是从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];
}
Run Code Online (Sandbox Code Playgroud)
这段代码有效,大部分时间也在详细信息视图中工作,这个视图被称为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];
}
Run Code Online (Sandbox Code Playgroud)
并且目标控制器正确地获取实体id并通过询问上下文来重构对象.然后,当我在详细视图控制器中时,我可以对实体进行更改,当我返回导航层次结构时,我会进行上下文保存.正是在这一点上,应用程序崩溃,正好在上下文保存时.不是经常,但不时.因为获取的结果控制器识别更改并提交给已取消分配的委托.
我现在几乎没有怀疑,我正在使用iOS 5和ARC,所以编译器应该(几乎)完全控制release和dealloc方法.我还使用具有简单导航层次结构的故事板,这应该保证整个先前的视图控制器链得到保留.
我还运行探测器进行内存泄漏/僵尸分析,但无法发现任何错误,相反我很高兴所有对象管理都很好.
我在这一点上没有多少猜测,所以请随意指出我可能忘记检查的内容,或者我在代码中看到错误的内容.
谢谢
Rob*_*ier 21
首先,关于ARC的说明.虽然ARC提供自动调零weak指针,但它不会使assign指针自动调零.为其委托NSFetchResultsController使用assign属性(请参阅参考资料NSFetchedResultsController.h):
@property(nonatomic, assign) id< NSFetchedResultsControllerDelegate > delegate;
Run Code Online (Sandbox Code Playgroud)
在您解除分配之前,您仍有责任将自己清除为代表.您通常这样做dealloc:
- (void)dealloc {
_fetchedResultsController.delegate = nil;
}
Run Code Online (Sandbox Code Playgroud)
你也可能想摆脱你的fetchedResultsController中viewWillDisappear:(包括移除自己作为委托).通常,当您在屏幕外时,您不希望抓取请求保持不变.(如果这样做,您可能应该管理模型对象而不是视图控制器中的提取,因为视图控制器可以在其视图在屏幕外的任何时候消失.)
你loadData很奇怪它创造了一个findAllEntities,但实际上是用的findAllPlants.这是一个错字还是一个错误?如果findAllPlants在ivar中有单独的提取请求,这也可能是您遇到问题的原因.
| 归档时间: |
|
| 查看次数: |
3307 次 |
| 最近记录: |