ios - 如何解决message sent to deallocated instance 这样的错误?
PHP中文网
PHP中文网 2017-04-17 17:27:46
[iOS讨论组]

这个错误产生应该是,一个消息实例已经被释放,但还向他发送消息导致的。

比如我现在有个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。这样不会造成循环引用吗?

PHP中文网
PHP中文网

认证0级讲师

全部回复(2)
ringa_lee

循环引用是当一个object1强引用了另一个object2,而这个object2同时又强引用了object1,这时由于俩个object引用计数都不为0,从而都无法释放内存。。。

拿你的最后一个block举例。。。因为self没有强引用block,所以在block中强引用self是没有关系的!

另外,_unsafe_unretained与_weak的区别在于当内存释放后前者指针不会销毁,会成为野指针,所以对野指针调用的话,会crash..一般消除循环引用都使用_weak或者手动置block为nil

对于你多线程访问UIViewController的问题,可以将UIViewController消失时,取消线程访问。。或者将UIViewController延迟释放。。。

黄舟

这边用__unsafe_unretained并没什么好处

不如用__weak, 这样你可以检查对象是否还在(如果对象不在了, 弱引用的值会变成nil)

后一个写法中, 如果self不引用(直接或间接)那个块, 就不是循环引用. 这样写会造成self更晚释放(不要这样写),不会因循环引用让self永远不释放.

热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号