提到runloop就必須和線程扯上關系了 runloop就像司機 線程就像車 沒有司機的車是死的 遲早藥丸
開發(fā)的時候可能會遇到一個頁面很多需要放在其他線程處理的情況 這時候我們可以開啟一個常駐線程 有什么邏輯都放在常駐線程
@property (nonatomic, strong) NSThread *childThread;
@property (nonatomic, assign) BOOL isCoast;
self.childThread = [[NSThread alloc] initWithTarget:self selector:@selector(run) object:nil];
[self.childThread start];
首先開啟我們的線程 綁定一個方法
然后重點來了 給這個線程的當前runloop添加一個NSPort 讓runloop跑起來
給這個線程分配任務就是喚醒車這個線程的一個source RunLoop Mode就是一系列輸入的source ,timer和以及observer
- (void)run
{
[[NSRunLoop currentRunLoop] addPort:[NSPort port] forMode:NSDefaultRunLoopMode];
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
NSLog(@"run");
self.isCoast = YES;
}
最后一句系統(tǒng)提供了三種run的方式
- (void)run;
- (void)runUntilDate:(NSDate *)limitDate;
- (BOOL)runMode:(NSRunLoopMode)mode beforeDate:(NSDate *)limitDate;
第一個是將接收器置于永久循環(huán)中,在此期間處理來自所有附加輸入源的數(shù)據(jù)。其實就是開啟Runloop
第二個是運行循環(huán)直到指定的日期,在此期間,它處理所有附加的輸入源的數(shù)據(jù)。
第三個是運行循環(huán)一次,阻塞在指定模式下的輸入,直到給定的日期到達
所以我們這里選擇第三種來開啟我們的常駐線程
然后我寫了個按鈕 點擊按鈕的時候進入耗時操作 按鈕的點擊方法如下 performSelector onThread:方法把任務放在指定線程處理 testMethod放在主線程是會阻塞主線程的
- (void)btnClick
{
[self performSelector:@selector(testMethod) onThread:self.childThread withObject:nil waitUntilDone:NO];
}
- (void)testMethod
{
for (int i = 10; i < 5000; i ++) {
@autoreleasepool{
NSData *data = UIImagePNGRepresentation([UIImage imageNamed:@"商務英語-首頁大圖"]);
}
}
}
這樣我們的控制器里就有一個常駐線程了 有什么邏輯 直接丟給它處理 記得UI操作回到主線程
重點:現(xiàn)在這樣退出頁面 頁面是不會釋放的 我開始也沒注意 后來在返回按鈕的方法里 test是個空方法
if (!self.isCoast) {
[self performSelector:@selector(test) onThread:self.childThread withObject:nil waitUntilDone:NO];
}
[self.navigationController popViewControllerAnimated:YES];
就可以正常的釋放頁面了 而頁面也多了一個常駐線程 美滋滋·······