NSTimer的迴圈引用問題

2021-08-11 08:05:03 字數 3185 閱讀 4748

`_timer = [nstimer scheduledtimerwithtimeinterval:1.0 target:self selector:@selector(countdown) userinfo:nil repeats:yes];`
@property (nonatomic,strong) nstimer *timer;第一種方法如下所示:

@inte***ce nstimer (jqusingblock)

+ (nstimer *)jq_scheduledtimerwithtimeinterval:(nstimeinterval)ti

block:(void(^)())block

repeats:(bool)repeats;

@end

@implementation nstimer (jqusingblock)

+ (nstimer *)lsz_scheduledtimerwithtimeinterval:(nstimeinterval)ti

block:(void(^)())block

repeats:(bool)repeats

+ (void)jq_blockinvoke:(nstimer *)timer

}@end

定義乙個nstimer的類別,在類別中定義乙個類方法。類方法有乙個型別為塊的引數(定義的塊位於棧上,為了防止塊被釋放,需要呼叫copy方法,將塊移到堆上)。使用這個類別的方式如下:

__weak viewcontroller *weakself = self;

_timer = [nstimer lsz_scheduledtimerwithtimeinterval:1.0

block:^

repeats:yes];

使用這種方案就可以防止nstimer對類的保留,從而打破了迴圈引用的產生。__strong viewcontroller *strongself = weakself主要是為了防止執行塊的**時,類被釋放了。在類的dealloc方法中,記得呼叫[_timer invalidate]

nsproxy本身是乙個抽象類,它遵循nsobject協議,提供了訊息**的通用介面。nsproxy通常用來實現訊息**機制和惰性初始化資源。

使用nsproxy,你需要寫乙個子類繼承它,然後需要實現init以及訊息**的相關方法。

1 //當乙個訊息**的動作nsinvocation到來的時候,在這裡選擇把訊息**給對應的實際處理物件

2 - (void)forwardinvocation:(nsinvocation *)aninvocation

3 4 //當乙個sel到來的時候,在這裡返回sel對應的nsmethodsignature

5 - (nsmethodsignature *)methodsignatureforselector:(sel)aselector

6 7 //是否響應乙個sel

8 + (bool)respondstoselector:(sel)aselector

訊息**涉及到三個核心方法

1 //訊息**第一步,在這裡可以動態的為類新增方法,這樣類自己就能處理了

2 +resolveinstancemethod:

3 //訊息**第二步,在第一步無法完成的情況下執行。這裡只是把乙個selector簡單的**給另乙個物件

4 - forwardingtargetforselector:

5 //訊息**第三步,在第二步也無法完成的情況下執行。將整個訊息封裝成nsinvocation,傳遞下去

6 - forwardinvocation:

訊息**機制使得**變的很靈活:乙個類本身可以完全不實現某些方法,它只要能**就可以了。

@inte***ce weakproxy : nsproxy

@property (weak,nonatomic,readonly)id target;

+ (instancetype)proxywithtarget:(id)target;

- (instancetype)initwithtarget:(id)target;

@end

@implementation weakproxy

- (instancetype)initwithtarget:(id)target

+ (instancetype)proxywithtarget:(id)target

- (void)forwardinvocation:(nsinvocation *)invocation

}- (nsmethodsignature *)methodsignatureforselector:(sel)aselector

- (bool)respondstoselector:(sel)aselector

@end

外部建立timer

self.timer = [nstimer timerwithtimeinterval:1

target:[weakproxy proxywithtarget:self]

selector:@selector(timerinvoked:)

userinfo:nil

repeats:yes];

原理如下:

我們把虛線處變成了弱引用。於是,controller就可以被釋放掉,我們在controller的dealloc中呼叫invalidate,就斷掉了runloop對timer的引用,於是整個三個淡藍色的就都被釋放掉了。

__weak subviewcontroller *weakself = self;

_timer = [nstimer scheduledtimerwithtimeinterval:1.0 repeats:yes block:^(nstimer * _nonnull timer) ];

ios10以後出現了乙個新的方法不需要傳入self,在block裡迴圈執行就可以

NSTimer中的迴圈引用

void viewdidload void p dosomething void p stopdosomething void dealloc 上面的 主要是利用定時器重複執行p dosomething方法,在合適的時候呼叫p stopdosomething方法使定時器失效.scheduledtim...

iOS中解決NSTimer迴圈引用的三種方式

今天有個人來公司面試,問了他平時在使用timer定時器時怎麼解決迴圈引用的問題。然後就得到了這樣乙個答案 weak typeof self weakself self self.timer nstimer scheduledtimerwithtimeinterval 1.0 target weaks...

迴圈引用問題

main.m 07 迴圈引用 created by kevin on 13 8 9.1.class的作用 僅僅告訴編譯器,某個名稱是乙個類 class person 僅僅告訴編譯器,person是乙個類 2.開發中引用乙個類的規範 1 在.h檔案中用 class來宣告類 2 在.m檔案中用 impo...