美文网首页
循环引用

循环引用

作者: 悟2023 | 来源:发表于2017-12-11 15:39 被阅读3次

    1、循环引用对App的影响

    内存无法释放 >> 性能降低 >> 闪退

    2、循环引用具体存在情景(相互包含、block、delegate、NSTimer)

    ----(假如有ZQViewControllerZQObject对象)

    • 相互包含
    //ZQViewController.m中是如下Code
    @interface ZQViewController ()
    @property (nonatomic,strong) ZQObject *                 object;
    @end
    
    @implementation ZQViewController
    - (void)dealloc {
        NSLog(@"循环引用该方法不会执行");
    }
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        self.object = [[ZQObject alloc] init];
        _object.viewController = self;
    }
    
    //ZQObject.h中是如下Code
    #import <Foundation/Foundation.h>
    @interface ZQObject : NSObject
    @property (nonatomic,strong) UIViewController  *      viewController;
    @end
    

    在如上Code情况中:
    ZQViewController强引用了ZQObject;同时ZQObject强引用了ZQViewController;这个时候由于二者的RetainCount不可能为0,所以导致对象无法释放。
    注:CFGetRetainCount((__bridge CFTypeRef)(_object))

    • block
    #import "ZQViewController.h"
    
    #import "ZQObject.h"
    @interface ZQViewController ()
    @property (nonatomic,strong) ZQObject *                 object;
    @end
    
    @implementation ZQViewController
    - (void)dealloc {
        NSLog(@"循环引用该方法不会执行");
    }
    - (void)viewDidLoad {
        [super viewDidLoad];
        //情况一:
        self.object = [[ZQObject alloc] init];
        self.object.testBlock = ^{
            [self doSomething];
        };
        //情况二:
        self.object = [[ZQObject alloc] init];
        __weak typeof(self) weakSelf = self;
        self.object.testBlock = ^{
            __strong typeof (weakSelf) strongSelf = weakSelf;
            [strongSelf doSomething];
        };
    }
    - (void)doSomething {
        NSLog(@"做一些事情");
    }
    
    #import <Foundation/Foundation.h>
    
    typedef void (^testBlock)(void);
    @interface ZQObject : NSObject
    @property (nonatomic, copy) testBlock                 testBlock;
    @end
    

    在如上Code情况中:
    block在copy时都会对block内部用到的对象(self)进行强引用的。
    ZQObject中的block的方法体里面又使用了ZQViewController,此时就出现了相互强引用,这个时候由于二者的RetainCount不可能为0,所以导致对象无法释放。

    • delegate
    #import "ZQViewController.h"
    #import "ZQObject.h"
    
    @interface ZQViewController ()
    <ObjectDelegate>
    
    @property (nonatomic,strong) ZQObject *                 object;
    @end
    
    @implementation ZQViewController
    
    - (void)dealloc {
        NSLog(@"循环引用该方法不会执行");
    }
    
    - (void)viewDidLoad {
        [super viewDidLoad];
    
        self.object = [[ZQObject alloc] init];
        _object.delegate = self;
    }
    
    #import <Foundation/Foundation.h>
    
    @protocol ObjectDelegate <NSObject>
    
    @end
    
    @interface ZQObject : NSObject
    @property (nonatomic, weak) id <ObjectDelegate> delegate;
    @end
    

    ZQViewController持有ZQObject对象,同时_object.delegate = self;ZQObject 持有ZQViewController```对象,delegate如果也是strong类型引用,二者的RetainCount不可能为0,所以导致对象无法释放。

    • NSTimer
      NSTimer 因为是比较特殊的情况,所以很容易被我们忽略。
    + (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti
                                         target:(id)aTarget
                                       selector:(SEL)aSelector
                                       userInfo:(nullable id)userInfo
                                        repeats:(BOOL)yesOrNo;
    

    方法的最后一个参数(repeats)为YES时,NSTimer会保留目标(target)对象,等到自身失效才释放。执行完任务后,一次性的定时器会自动失效;重复性的定时器,需要主动调用invalidate方法才会失效。
    创建定时器时,当前控制器引用而定时器了,在给定时器添加任务时,定时器保留了self(当前控制器对象).这里就出现了循环引用。

    相关文章

      网友评论

          本文标题:循环引用

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