IOS開發時可能會想用到延時執行一個函數。學會用這個函數有時會讓代碼簡單很多。
下文出現的self均指當前頁面控制器(ViewController)
基本方法:
1 @interface NSObject (NSDelayedPerforming) 2 3 //設置延遲執行,delay單位為秒 4 - (void)performSelector:(SEL)aSelector withObject:(id)anArgument afterDelay:(NSTimeInterval)delay inModes:(NSArray *)modes; 5 6 - (void)performSelector:(SEL)aSelector withObject:(id)anArgument afterDelay:(NSTimeInterval)delay; 7 8 //取消已設置的延遲執行 9 + (void)cancelPreviousPerformRequestsWithTarget:(id)aTarget selector:(SEL)aSelector object:(id)anArgument; 10 11 + (void)cancelPreviousPerformRequestsWithTarget:(id)aTarget; 12 13 @end
如若設置下面的延遲執行方法:
1 [self performSelector:@selector(didRuninCurrModel:) withObject:[NSNumber numberWithBool:YES] afterDelay:3.0f]; 2 3 [self performSelector:@selector(didRuninCurrModelNoArgument) withObject:nil afterDelay:3.0f];
若取消對應的延遲執行方法可用下面方法:
1 [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(didRuninCurrModel:) object:[NSNumber numberWithBool:YES]]; 2 3 [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(didRuninCurrModelNoArgument) object:nil];
需要注意的是參數的一致性,如下面的取消無法實現:
1 [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(didRuninCurrModel:) object:[NSNumber numberWithBool:NO]]; 2 3 [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(didRuninCurrModel:) object:nil];
下面方法可以一次取消所有的延遲執行:
1 [NSObject cancelPreviousPerformRequestsWithTarget:self]; 2 3 [[self class] cancelPreviousPerformRequestsWithTarget:self];
注意:設置延遲執行可能會導致內存泄漏:
(這個我也不是特別懂,不能說沒遇到過,只是現在的水平還達不到那個高度)
搜集網上的資料說:當頁面需要dealloc時,若延遲函數還沒有執行會引發內存泄漏。
個人認為如果像這樣設置延遲執行:
1 [self performSelector:@selector(function) withObject:self afterDelay:30.0f];
若在頁面需要dealloc時沒有執行延遲函數,從self的引用計數來看應該會出現內存泄漏。
但是不清楚當參數withObject:nil 時會不會改變self的引用計數。
另外,我在一次練習中用到了這個延遲執行,但是,最終失敗了,分享一下我當時的做法和現在的一些想法。
TestApp是一個NavigationController控制的二級頁面。當點擊首頁的TableViewCell會跳轉到第二級頁面。然后我的延遲執行是在第二級頁面設置的。延遲執行設置和執行方面正常,但當我設置好延遲執行,返回主頁然后再進入該第二級頁面,無法取消之前設置的延遲執行。
NavigationController控制的頁面跳轉,是把頁面控制器放到一個棧里,根據前進還是返回進行入棧和出棧的。后來分析了下,像上面,我第二次進入第二級頁面已經不是第一次進入的那個第二級頁面了,所以不能取消第一次設置的延遲執行。但是延遲執行能夠執行成功,則是說明第一次的那個第二級頁面雖然出棧了但沒有被dealloc掉,這個應該是因為設置延遲執行會增加頁面的引用計數,而和設置引用計數時有沒有設置withObject:self 或者withObject:nil 沒有關系。
不知道我的想法對不對,大神不要嘲笑,歡迎指導!