為什么要寫這篇破事水
這些代碼來自于年初某短視頻巨廠面試時候的即興表演腹侣,
當時寫的是偽代碼叔收,現(xiàn)在把他補完整
面試官提出來的要求如下:
NSTimer用起來有很多注意點,不方便傲隶,要求實現(xiàn)一個
+ (NSTimer *)xx_scheduledTimerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(nullable id)userInfo repeats:(BOOL)yesOrNo;
1.解決循環(huán)引用
2.aTarget釋放時自動invalidate
3.多個timer可以同時存在
那他滿意了嗎
看他笑的挺滿意的饺律,那一輪面試也確實過了,可惜二面沒表現(xiàn)好……我懷疑是被白剽思路(不可能的你想太多了)
那在哪里可以拿到demo呢伦籍?
那怎么實現(xiàn)
當時思考了2分鐘拿出以下方案蓝晒,大致就是用了備用接收者和完整消息轉(zhuǎn)發(fā)來完成這個方法腮出,貼一點關(guān)鍵代碼帖鸦,完整demo代碼在上面的github里
- NSTimer+Easy方法
+ (NSTimer *)clc_scheduledTimerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(id)userInfo repeats:(BOOL)yesOrNo {
CLCTimerObject *obj = [[CLCTimerObject alloc] init];
obj.target = aTarget; //weak
obj.myTimer = [NSTimer scheduledTimerWithTimeInterval:ti target:obj selector:aSelector userInfo:userInfo repeats:yesOrNo];
//timer 持有obj,obj弱引用aTarget胚嘲,obj同時也負責處理aTarget釋放時timer的invalidate
return obj.myTimer;
}
2.CLCTimerObj屬性
//一個持有aTarget作儿,一個持有timer,都是弱引用馋劈,反正timer啟動了就會被掛住
@property (nonatomic, weak) NSObject *target;
@property (nonatomic, weak) NSTimer *myTimer;
3.CLCTimerObj實現(xiàn)
//用runtime的備用接收者機制去判斷aTarget釋放了沒
- (id)forwardingTargetForSelector:(SEL)aSelector {
//target還沒釋放 --> 返回的是self.target對象
//target被釋放了 --> 返回的是nil攻锰,進入下一步消息轉(zhuǎn)發(fā)
NSLog(@"send to aTarget");
return self.target;
}
//用完整消息轉(zhuǎn)發(fā)兜底,上一步返回nil時就invalidate掉timer
- (NSMethodSignature *)methodSignatureForSelector:(SEL)selector {
NSLog(@"return Signature");
return [NSMethodSignature signatureWithObjCTypes:"v@:@@"]; //隨便簽妓雾,無所謂啦
}
- (void)forwardInvocation:(NSInvocation *)invocation {
NSLog(@"call forwordInvocation");
[self _invalidateTimer];
}
- (void)_invalidateTimer {
if (self.myTimer) {
[self.myTimer invalidate];
self.myTimer = nil;
}
}
利弊分析
好處
1.防止發(fā)生循環(huán)引用娶吞、timer沒有好好手動invalidate等問題,傻瓜式timer(只是做保護械姻,還是建議手寫invalidate)
2.一次性倒計時View(比如543210開始直播)不需要把timer掛住當屬性妒蛇,時間到了自己removeFromSuperview引用計數(shù)歸零變成nil就行了,不需要管timer楷拳,他是自動的
3.自動停止能確保NSTimer的invalidate和init在同一個線程里
孬處
- 維護起來不容易閱讀(“我艸這timer啥時候釋放的绣夺?”)