NSObject 中執行Selector 的相關方法,nsobjectselector

來源:互聯網
上載者:User

NSObject 中執行Selector 的相關方法,nsobjectselector
1. 對當前Run Loop中Selector Sources的取消

NSObject中的performSelector:withObject:afterDelay:方法將會在當前線程的Run Loop中根據afterDelay參數建立一個Timer,如果沒有調用有inModes參數的方法,該Timer會運行在當前Run Loop的預設模式中,也就是NSDefaultRunLoopMode定義的模式中。

performSelector:withObject:afterDelay:方法的使用看起來還是很簡單的。這裡講另外一個輔助函數,NSObject中靜態cancelPreviousPerformRequestsWithTarget方法。該方法就是專門用來取消取消performSelector:withObject:afterDelay:方法所建立的Selector source(內部上就是一個Run Loop的Timer source)。因此該方法和performSelector:withObject:afterDelay:方法一樣,只限於當前Run Loop中。

 

我們可以利用cancelPreviousPerformRequestsWithTarget直接取消一個對象在當前Run Loop中的所有未執行的performSelector:withObject:afterDelay:方法所產生的Selector Sources,如下代碼:

- (void)viewDidLoad
{
[super viewDidLoad];


[self performSelector:@selector(test:) withObject:nil afterDelay:1];
[self performSelector:@selector(test:) withObject:@"mgen" afterDelay:2];
[NSObject cancelPreviousPerformRequestsWithTarget:self];
}

- (void)test:(id)obj
{
NSLog(@"調用成功: %@", obj);
}

不會有任何輸出,因為兩個調用都被取消了。

 

如果想取消單獨一個的話,需使用cancelPreviousPerformRequestsWithTarget:selector:object:方法,注意selectorobject參數需要一一對應。如下代碼:

- (void)viewDidLoad
{
[super viewDidLoad];

[self performSelector:@selector(test:) withObject:[NSNumber numberWithInt:26] afterDelay:1];
[self performSelector:@selector(test:) withObject:[NSNumber numberWithInt:17] afterDelay:2];
[self performSelector:@selector(test:) withObject:[NSNumber numberWithInt:17] afterDelay:3];
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(test:) object:[NSNumber numberWithInt:17]];
}

- (void)test:(id)obj
{
NSLog(@"調用成功: %@", obj);
}

 

只會輸出:

調用成功: 26

其他兩個Selector都被取消了。

 

返回目錄

2. 在NSThread中執行Selector

這個話題很簡單,直接通過NSObjectperformSelectorInBackground:withObject:方法就可以,如下代碼:

- (void)viewDidLoad
{
[super viewDidLoad];

[self threadInfo:@"UI"];
[self performSelectorInBackground:@selector(test:) withObject:nil];

}

- (void)test:(id)obj
{
@autoreleasepool
{
[self threadInfo:@"test"];
}
}
- (void)threadInfo:(NSString*)category
{
NSLog(@"%@ - %@", category, [NSThread currentThread]);
}

 

輸出:

UI - <NSThread: 0x71639e0>{name = (null), num = 1}
test - <NSThread: 0x7176ad0>{name = (null), num = 3}

 

這個方法完全等效於NSThreaddetachNewThreadSelector:toTarget:withObject:靜態方法,那麼上面NSObjectperformSelectorInBackground:withObject:方法調用完全可以替換成:

[NSThread detachNewThreadSelector:@selector(test:) toTarget:self withObject:nil];

 

當然,使用者也可以自行手動建立一個NSThread來完成上述功能,代碼如下:

NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(test:) object:nil];
[thread start];

這兩種方法運行後的輸出是和第一種類似的。

 

返回目錄

3. 在NSThread中的Run Loop中執行Selector

這裡需要的方法是NSObjectperformSelector:onThread:withObject:waitUntilDone:方法。由於是在另一個NSThread中執行Selector,所以我們需要手動開始Run Loop。首先需要在ViewController中定義兩個欄位,分別是NSThread和控制線程內Run Loop執行的flag。

@interface ViewController ()
{
NSThread *_thread;
BOOL _isNewThreadAborted;
}

 

接下來做的是執行這個線程,並且線上程中手動調用NSRunLooprunMode:beforeDate:方法。這裡注意,如果Run Loop沒有任何Source的話,該方法會立即返回,所以需要建立一個迴圈來持續調用Run Loop的runMode:beforeDate:方法。並在Selector執行結束後同時嘗試結束這個迴圈。最終代碼如下:

- (void)viewDidLoad
{
[super viewDidLoad];

[self threadInfo:@"UI"];

_isNewThreadAborted = NO;
_thread = [[NSThread alloc] initWithTarget:self selector:@selector(newThread:) object:nil];
//開始線程
[_thread start];
//在另一個線程中的Run Loop中執行Selector
[self performSelector:@selector(test:) onThread:_thread withObject:nil waitUntilDone:NO];
}

//在新線程中建立並開始一個NSRunLoop
- (void)newThread:(id)obj
{
@autoreleasepool
{
NSRunLoop *currentRunLoop = [NSRunLoop currentRunLoop];
while (!_isNewThreadAborted)
{
[currentRunLoop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
}
NSLog(@"線程停止");
}
}

//Selector執行
- (void)test:(id)obj
{
[self threadInfo:@"test"];
_isNewThreadAborted = YES;
}

- (void)threadInfo:(NSString*)category
{
NSLog(@"%@ - %@", category, [NSThread currentThread]);
}

 

輸出:

UI - <NSThread: 0x717e7e0>{name = (null), num = 1}
test - <NSThread: 0x8078a80>{name = (null), num = 3}
線程停止

最後注意performSelector:onThread:withObject:waitUntilDone:方法中最後的waitUntilDone參數,如果傳YES的話,當前線程會等待Selector在另一個線程中執行完畢後繼續執行。

4. UIPinchGestureRecognizer 與 NSObject Selector 的關聯 

    if (recognizer.state == UIGestureRecognizerStateChanged) {

         [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(XXXSetNeedsDisplay) object:recognizer];

    // 相關的方法...

         } else if (recognizer.state == UIGestureRecognizerStateEnded) {

        [self performSelector:@selector(XXXSetNeedsDisplay) withObject:recognizer afterDelay:1.0f];

    }

 

相關文章

聯繫我們

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