这个错误产生应该是,一个消息实例已经被释放,但还向他发送消息导致的。
比如我现在有个ViewViewController 。进入这个页面,我创建一个多线程,请求服务端的数据。
当我离开了这个页面。观察dealloc发现,此时页面已经被释放了。
但那个多线程任务他不知道啊,因为网速慢,他还在傻傻的执行。执行完了,他发出一系列的动作,比如更新页面什么的,因为ViewViewController已经被释放了,所以就出现了那样的错误,造成闪退。不知道应该如何避免或者解决这个问题呢?
----------问题补充-------------
__unsafe_unretained __typeof(self) weakSelf = self;
[self.travelService loadTravelDetailData:^(ApiResponser *apiResponser) {
[weakSelf bindUserValue];
[weakSelf.myTableView reloadData];
} failBlock:^(NSError *error) {
}];
原本是这样的,页面退出之后就可以释放。但是会闪退。
现在我索性变成这样。因为循环引用,页面即使切换掉内存也没有被释放。但是不闪退了。
[self.travelService loadTravelDetailData:^(ApiResponser *apiResponser) {
[self bindUserValue];
[self.myTableView reloadData];
} failBlock:^(NSError *error) {
}];
-----------
有点搞不清楚状况。比如我查看了wordpress的ios客户端。
void (^successBlock)(RemoteMedia *media) = ^(RemoteMedia *media) {
[self.managedObjectContext performBlock:^{
NSError * error = nil;
Media *mediaInContext = (Media *)[self.managedObjectContext existingObjectWithID:mediaObjectID error:&error];
if (!mediaInContext){
DDLogError(@"Error retrieving media object: %@", error);
if (failure){
failure(error);
}
return;
}
[self updateMedia:mediaInContext withRemoteMedia:media];
mediaInContext.remoteStatus = MediaRemoteStatusSync;
[[ContextManager sharedInstance] saveContext:self.managedObjectContext withCompletionBlock:^{
if (success) {
success();
}
}];
}];
};
到处都是self,而不是weak。这样不会造成循环引用吗?
循环引用是当一个object1强引用了另一个object2,而这个object2同时又强引用了object1,这时由于俩个object引用计数都不为0,从而都无法释放内存。。。
拿你的最后一个block举例。。。因为self没有强引用block,所以在block中强引用self是没有关系的!
另外,_unsafe_unretained与_weak的区别在于当内存释放后前者指针不会销毁,会成为野指针,所以对野指针调用的话,会crash..一般消除循环引用都使用_weak或者手动置block为nil
对于你多线程访问UIViewController的问题,可以将UIViewController消失时,取消线程访问。。或者将UIViewController延迟释放。。。