iOS中NSRunLoop的模式

來源:互聯網
上載者:User
一.NSRunLoop

在Cocoa中,每個線程(NSThread)對象中內部都有一個run loop(NSRunLoop)對象用來迴圈處理輸入事件,處理的事件包括兩類,一是來自Input sources的非同步事件,一是來自Timer sources的同步事件;
run Loop在處理輸入事件時會產生通知,可以通過Core Foundation向線程中添加run-loop observers來監聽特定事件,以在監聽的事件發生時做附加的處理工作。

每個run loop可運行在不同的模式下,一個run loop mode是一個集合,其中包含其監聽的若干輸入事件來源,定時器,以及在事件發生時需要通知的run loop observers。運行在一種mode下的run loop只會處理其run loop mode中包含的輸入源事件,定時器事件,以及通知run loop mode中包含的observers。
Cocoa中的預定義模式有: Default模式
定義:NSDefaultRunLoopMode (Cocoa) kCFRunLoopDefaultMode (Core Foundation)
描述:預設模式中幾乎包含了所有輸入源(NSConnection除外),一般情況下應使用此模式。 Connection模式
定義:NSConnectionReplyMode(Cocoa)
描述:處理NSConnection對象相關事件,系統內部使用,使用者基本不會使用。 Modal模式
定義:NSModalPanelRunLoopMode(Cocoa)
描述:處理modal panels事件。 Event tracking模式
定義:UITrackingRunLoopMode(iOS) NSEventTrackingRunLoopMode(cocoa)
描述:在拖動loop或其他user interface tracking loops時處於此種模式下,在此模式下會限制輸入事件的處理。例如,當手指按住UITableView拖動時就會處於此模式。 Common模式
定義:NSRunLoopCommonModes (Cocoa) kCFRunLoopCommonModes (Core Foundation)
描述:這是一個偽模式,其為一組run loop mode的集合,將輸入源加入此模式意味著在Common Modes中包含的所有模式下都可以處理。在Cocoa應用程式中,預設情況下Common Modes包含default modes,modal modes,event Tracking modes.可使用CFRunLoopAddCommonMode方法想Common Modes中添加自訂modes。

擷取當前線程的run loop mode

NSString* runLoopMode = [[NSRunLoop currentRunLoop] currentMode];

二.NSTimer、NSURLConnection與UITrackingRunLoopMode

NSTimer與NSURLConnection預設運行在default mode下,這樣當使用者在拖動UITableView處於UITrackingRunLoopMode模式時,NSTimer不能fire,NSURLConnection的資料也無法處理。
NSTimer的例子:
在一個UITableViewController中啟動一個0.2s的迴圈定時器,在定時器到期時更新一個計數器,並顯示在label上。

-(void)viewDidLoad{    label =[[[UILabel alloc]initWithFrame:CGRectMake(10, 100, 100, 50)]autorelease];    [self.view addSubview:label];    count = 0;    NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval: 1                                                      target: self                                                    selector: @selector(incrementCounter:)                                                    userInfo: nil                                                     repeats: YES];}- (void)incrementCounter:(NSTimer *)theTimer{    count++;    label.text = [NSString stringWithFormat:@"%d",count];}

在正常情況下,可看到每隔0.2s,label上顯示的數字+1,但當你拖動或按住tableView時,label上的數字不再更新,當你手指離開時,label上的數字繼續更新。當你拖動UItableView時,當前線程run loop處於UIEventTrackingRunLoopMode模式,在這種模式下,不處理定時器事件,即定時器無法fire,label上的數字也就無法更新。
解決方案,一種方法是在另外的線程中處理定時器事件,可把Timer加入到NSOperation中在另一個線程中調度;還有一種方法時修改Timer啟動並執行run loop模式,將其加入到UITrackingRunLoopMode模式或NSRunLoopCommonModes模式中。

[[NSRunLoop currentRunLoop] addTimer:timer forMode:UITrackingRunLoopMode];

[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];

另外一種是放到NSThread中 [objc]  view plain copy - (void)viewDidLoad{       [super viewDidLoad];       NSLog(@"主線程 %@", [NSThread currentThread]);       //建立並執行新的線程       NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(newThread) object:nil];       [thread start];   }   - (void)newThread{      @autoreleasepool{       //在當前Run Loop中添加timer,模式是預設的NSDefaultRunLoopMode       [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(timer_callback) userInfo:nil repeats:YES];       //開始執行新線程的Run Loop,如果不啟動run loop,timer的事件是不會響應的       [[NSRunLoop currentRunLoop] run];       }   }   - (void)timer_callback{       NSLog(@"Timer %@", [NSThread currentThread]);   }  

NSURLConnection也是如此,見SDWebImage中的描述,以及SDWebImageDownloader.m代碼中的實現。修改NSURLConnection的運行模式可使用scheduleInRunLoop:forMode:方法。

NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:15]; NSURLConnection *connection = [[[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:NO]autorelease];[connection scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];[connection start];

參考:
Threading Programming Guide – Run Loops
NSRunLoop Class Reference
NSURLConnection Class Reference
NSTimer Class Reference
CFRunLoop wiki
SDWebImage
TestButtonDown
NSTimerDoesntRunWhenMenuClicked

本文出自 清風徐來,水波不興 的部落格,轉載時請註明出處及相應連結。

本文永久連結: http://www.winddisk.com/2012/06/29/nstimer_run_loop_modes/

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.