美文网首页零碎知识点iOS
[转]iOS中判定delegate是否已经被释放掉

[转]iOS中判定delegate是否已经被释放掉

作者: lugic | 来源:发表于2016-12-12 21:07 被阅读476次

    在iOS的实际开发过程中,常常会遇到内存管理的问题。有一种特别常见的内存管理问题是delegate释放引起的,这种问题是最难发现,也是最难修复的。下面介绍一下这种问题的简单解决办法。

    首先说一下原理,由于某个对象release之后(在不方便置为nil时,比如UIViewController作为delegate),其指针仍不为空,还占有内存地址,因此不能直接用类似delegate == nil的判定方法,而且这时给该delegate发送任何消息,程序都会在此处crash。

    再来详说解决办法,其实这里用到了一个技巧。主要思路是,delegate被释放之后,其占有内存地址,其值也是内存地址,而不是某个具体的对象。因此,可以重载delegate的赋值操作,在该操作里面记下该delegate的类的类型,然后在使用delegate的地方,检测当前的delegate是否与之前记下的delegate是同一个类型,如果是,则说明该delegate没有被释放,如果不是,那说明被释放了,那就别发起回调了。

    示例代码:

    注意,要引用 #import "objc/runtime.h"头文件

    AClass.h
    @protocol TestDelegate <NSObject>
    
    - (void)delegateMethod;
    
    @end
    
    @interface Aclass : NSObject {
            Class     _orignalCls;
            id<TestDelegate>   _delegate;
    }
    
    
    @property (nonatomic, asssign)  id<TestDelegate>   delegate;
    
    
    @end;
    
    
    AClass.m
    
    - (id)init {
         self = [super init];
         if(self){
         ///////
         }
         return self;
    }
    
    
    - (void)setDelegate:(id<TestDelegate>)delegate{
          _delegate = delegate;
          _orignalCls = object_getClass(delegate);/**这是关键*/
    }
    
    
    //回调函数
    - (void)callbackInvoke{
        if(self.delegate){
            Class currentCls = object_getClass(self.delegate);
            if(currentCls == _orignalCls){
                 //delegate没有释放发起回调
                 if(self.delegate respondsToSelector(delegateMethod)){
                           [self.delegate delegateMethod];
                 }
            }
        }
    }
    
    @end
    

    后记:因为object_getClass()是动态编译的,在程序运行时能够准确的得到当前指针所指向的对象内容,所以这几乎是得到delegate类类型的唯一办法。

    相关文章

      网友评论

        本文标题:[转]iOS中判定delegate是否已经被释放掉

        本文链接:https://www.haomeiwen.com/subject/uscvmttx.html