iOS中解決NSTimer循環引用的三種方式

圖片描述

逆水行舟 不進則退

今天有我的來公司面試,問了他平時在使用Timer定時器時怎麼解決循環引用的問題。
而後就獲得了這樣一個答案:面試

__weak typeof(self) weakSelf = self;
    self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:weakSelf selector:@selector(fire) userInfo:nil repeats:YES];

這種方式不能解決循環引用的緣由是:在NSTimer的內部會對當前的weakSelf引用計數+1atom

聲明變量

@property (nonatomic, strong, nullable) NSObject *target;
    @property (nonatomic, strong, nullable) NSTimer *timer;

第一種:NSTimer提供的API

使用NSTimer提供的API,在block中執行定時任務spa

__weak typeof(self) weakSelf = self;
    self.timer = [NSTimer scheduledTimerWithTimeInterval:1 repeats:YES block:^(NSTimer * _Nonnull timer) {
        [weakSelf fire];
    }];

引用邏輯
self強引用timer弱引用targetcode

第二種: 藉助runtime給對象添加消息處理的能力

引用邏輯
self強引用timer強引用target對象

_target = [[NSObject alloc] init];
    class_addMethod([_target class], @selector(fire), class_getMethodImplementation([self class], @selector(fire)), "v@:");
    self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:_target selector:@selector(fire) userInfo:nil repeats:YES];

第三種:經過消息轉發的方法的方式

建立一個集成自NSProxy的類PHJProxy 聲明一個target圖片

#import <Foundation/Foundation.h>
    #import <objc/runtime.h>
    
    @interface PHJProxy : NSProxy
    
    @property (nonatomic, weak) id target;
    
    @end

PHJProxy的實現get

@implementation PHJProxy
    // 發送給target
    - (void)forwardInvocation:(NSInvocation *)invocation {
        [invocation invokeWithTarget:self.target];
    }
    // 給target註冊一個方法簽名
    - (nullable NSMethodSignature *)methodSignatureForSelector:(SEL)sel {
        return [self.target methodSignatureForSelector:sel];
    }
    
    @end

PHJProxy 和 NSTimer的使用it

self.proxy = [PHJProxy alloc];
    self.proxy.target = self;
    self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self.proxy selector:@selector(fire) userInfo:nil repeats:YES];

引用邏輯
self強引用timer強引用proxy弱引用selfio

相關文章
相關標籤/搜索