RunLoop機制理解

來源:互聯網
上載者:User

標籤:

一、淺識RunLoop

  RunLoop在開發中我們一直在用,但是沒有注意他。要想理解RunLoop,首先我們需要先瞭解一下程式運行機制。

  程式運行機制:我們都知道OC是運行時語言,也就是說對象的類型是在程式啟動並執行時候確定的。並調用類與對象相應的方法。但是最終代碼的執行始終是面向過程的。線程也是一樣:一個線程從開始代碼執行,到結束代碼銷毀。app如何?這樣的機制:app從運行開始一直處於待命狀態,接收到事件之後執行操作,操作完成後繼續等待相應,直到程式終止運行。這樣的管理線程執行任務的機制就是RunLoop機制。線程在執行中的休眠和啟用就是由RunLoop對象進行管理的。

二、RunLoop與線程的關係

  RunLoop是用來管理線程的。每一個線程都有一個RunLoop對象。可以通過具體的方法去獲得。但是需要注意:雖然每一個線程都可以擷取RUnLoop對象,但是並不是每一個線程中都有執行個體對象,我們可以這樣理解:如果我們不擷取RunLoop,這個RunLoop就不存在,我們擷取時,如果不存在,就會去建立。在主線程中,這個MainRunLoop是預設建立並運行啟用的。

三、NSRunLoop

  NSRunLoop是Cocoa架構中的類,與之對應的是在Core Fundation中有一個CFRunLoopRef類。這兩者的區別是前者不是安全執行緒的,而CFRunLoopRef是安全執行緒的。

1、擷取主線程的NSRunLoop

//擷取主線程的NSRunLoop+(NSRunLoop *)mainRunLoop;

2、擷取當前線程的NSRunLoop

//擷取當前線程的RunLoop:有的話就直接擷取,沒有的話就自動建立+(NSRunLoop *)currentRunLoop;

3、NSRunLoop的執行模式

//擷取當前runloop的執行模式@property(readonly,copy)NSString *currentMode;//兩種執行模式//預設的模式,接收大部分輸入源的響應NSString *const NSDefaultRunLoopMode;//多種模式的集合NSString *const NSRunLoopCommonModes;

4、擷取RunLoop的CFRunLoopRef對象

//擷取RunLoop的CFRunLoopRef對象-(CFRunLoopREF)getCFRunLoop;

5、將定時器添加到RunLoop中

//將定時器添加到runloop中-(void)addTimer:(NSTimer *)timer forMode:(NSString *)mode;

6、擷取下個回應時間

-(NSDate *)limitDateForMode:(NSString *)mode;

定時器的執行,其實並不是按照時間段額間隔進行調用方法,而是在定時器註冊到RunLoop中後,RunLoop會設定一個一個的時間點進行調用,例如,5,10,15,20等等。如果錯過了某個時間點,定時器並不會延遲調用,而是直接等待下一個時間點調用,所以定時器並不是準確的。

7、在某個時間期限前接收相應

-(void)aceptInputForMode:(NSString *)mode beforeDate:(NSDate *)limitDate;

8、開始運行

-(void)run;

9、到某個時間點運行

-(void)runUntilDate:(NSDate *)limitDate;

10、在某個期限前運行

-(BOOL)runMode:(NSString *)mode beforeDate:(NSDate *)limitDate;

11、

- (void)addPort:(NSPort *)aPort forMode:(NSString *)mode;添加輸入源連接埠到runloop中,NSPort對象可以理解為詳細的載體,會傳遞訊息與其代理。- (void)removePort:(NSPort *)aPort forMode:(NSString *)mode;將某個輸入源連接埠移除

 

四、RunLoop的調用

一般情況下我們很少去顯式調用或者啟動RunLoop,但是下邊的情況需要手動設定。

1、在分線程中使用定時器

定時器的實現是基於RunLoop的,平時我們使用定時器或許並沒有對RunLoop做什麼操作,那是因為主線程的RunLoop預設是開啟啟動並執行,如果我們進行如下操作:

-(void)viewDidLoad{  [super viewDidLoad];  dispatch_queue_t queue = dispatch_queue_create("myQueue",DISPATCH_QUEUE_CONCURRENT); dispatch_async(queue,^{    NSTimer *timer = [NSTimer scheduledTimerWithTimerInterval:1 target:self selector:@selector(time) userInfo:nil repeats:YES];});     }-(void)time{NSLog(@"runTimer");}

此時運行,控制台不會輸出runTimer。我們必須線上程中手動的執行如下代碼:

[[NSRunLoop currentRunLoop] run];

這樣定時器才可以正常工作。

2、當線程中使用如下的方法時

某些延遲函數和選取器在分線程中的使用,我們必須手動開始RunLoop

@interface NSObject (NSDelayedPerforming)- (void)performSelector:(SEL)aSelector withObject:(id)anArgument afterDelay:(NSTimeInterval)delay inModes:(NSArray *)modes;- (void)performSelector:(SEL)aSelector withObject:(id)anArgument afterDelay:(NSTimeInterval)delay;+ (void)cancelPreviousPerformRequestsWithTarget:(id)aTarget selector:(SEL)aSelector object:(id)anArgument;+ (void)cancelPreviousPerformRequestsWithTarget:(id)aTarget;- (void)performSelector:(SEL)aSelector target:(id)target argument:(id)arg order:(NSUInteger)order modes:(NSArray *)modes;- (void)cancelPerformSelector:(SEL)aSelector target:(id)target argument:(id)arg;- (void)cancelPerformSelectorsWithTarget:(id)target;

五、其他

輸入源被註冊到RunLoop中時會有方法進行remove。但是定時器沒有remove,但是它的invalidate方法可以將其從RunLoop中移除。invalidate是重要的也是唯一的將定時器從RunLoop中登出的方法,所以如果我們建立了定時器,就一定要再不適用的時候調用invalidate方法。

六、附

參考自:http://my.oschina.net/u/2340880/blog/491966

RunLoop機制理解

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.