Runloop的概念
Runloop的存在主要就是為了線程?;?,線程?;钍菫榱司€程能夠及時的處理事件,不會在其執行完之后立刻釋放。Node.js是基于V8引擎工作的,它是單線程操作的,但是Node的執行效率并不低,因為Node有事件輪詢和異步回調的機制,而Runloop就像是一個事件輪詢。
Runloop與線程
線程剛創建時并沒有 RunLoop,不主動獲取的話,一直都不會有Runloop。RunLoop 的創建是發生在第一次獲取時,RunLoop 的銷毀是發生在線程結束時。只能在一個線程的內部獲取其 RunLoop。
RunLoop的使用
1.NSTimer使用時,在ScrollView滑動時失效的問題。
這是因為主線程的 RunLoop 里有兩個預置的 Mode:kCFRunLoopDefaultMode 和 UITrackingRunLoopMode。這兩個 Mode 都已經被標記為"Common"屬性。DefaultMode 是 App 平時所處的狀態,TrackingRunLoopMode 是追蹤 ScrollView 滑動時的狀態。當你創建一個 Timer 并加到 DefaultMode 時,Timer 會得到重復回調,但此時滑動一個ScrollView時,RunLoop 會將 mode 切換為 TrackingRunLoopMode,這時 Timer 就不會被回調,并且也不會影響到滑動操作。
有時你需要一個 Timer,在兩個 Mode 中都能得到回調,解決辦法就是將 Timer 加入到頂層的 RunLoop 的 "commonModeItems" 中。"commonModeItems" 被 RunLoop 自動更新到所有具有"Common"屬性的 Mode 里去。
timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(setProgress) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:progressTimer forMode:NSRunLoopCommonModes];
2.子線程調用performSelector:afterDelay:失效的問題
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
//創建子線程
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(startThread) object:nil];
[thread start];
}
-(void)startThread{
//此時失效
[self performSelector:@selector(log:) withObject:@"dog" afterDelay:2];
//不會失效
dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, 2*NSEC_PER_SEC);
dispatch_after(time, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[self log:@"cow"];
});
}
-(void)log:(NSString *)string{
NSLog(@"%@++++",string);
}
這是因為調用 NSObject 的 performSelecter:afterDelay: 后,其內部會創建一個 Timer 并添加到當前線程的 RunLoop 中。所以如果當前線程沒有 RunLoop,則這個方法會失效。
3.動態UITableView緩存高度
TableView在緩存高度的時候,我們為了保持界面的流暢性會在頁面停止滑動的時候去計算cell的高度。
//獲取觀察者 觀察Runloop的mode狀態
CFRunLoopObserverRef observer = CFRunLoopObserverCreateWithHandler(kCFAllocatorDefault, kCFRunLoopBeforeWaiting, true, 0, ^(CFRunLoopObserverRef observer, CFRunLoopActivity _) {
if () {
CFRunLoopRemoveObserver(runLoop, observer, runLoopMode); CFRelease(observer); // 注意釋放,否則會造成內存泄露
return;
}
//主線程 NSDefaultRunLoopMode 進行計算
[self performSelector:@selector(fd_precacheIndexPathIfNeeded:) onThread:[NSThread mainThread] withObject:indexPath waitUntilDone:NO modes:@[NSDefaultRunLoopMode]];
}
);
愛生活,愛運動,熱愛交流,歡迎討論!