的completionHandler
非常存在可能導致一個在邏輯上推斷setGroupWithName
是一個異步方法。這是iOS開發中的一種常見編程模式:在前臺(在此期間用戶界面將被凍結)中執行一些可能耗時的進程,而不是在後臺異步執行它,但在此情況下爲,completionHandler
,這樣您可以確定在異步過程完成時應該發生什麼。
在這種情況下,它看起來像你調用setGroupWithName
,在一些後臺線程/隊列的理解,雖然這是發生,你會繼續在主線程(在你的情況下,在該NSLog
語句),確保您的應用在緩慢操作完成時保持響應。但是,當完成setGroupWithName
的異步後臺操作時,它將執行由completionHandler
(在您的情況中,s
設置爲@"something"
)代表的代碼塊。
如果你把一個NSLog
聲明completionHandler
塊,在那裏你設置s
到@"something"
裏面,你可能會看到,它是你的setGroupWithName
調用後,對現有NSLog
語句之後發生的好。
爲了說明的例子中,這裏是具有completionHandler
參數,即NSURLConnection
類方法,sendAsynchronousRequest
標準可可方法的一個例子。
問題是如何執行緩慢的操作,但仍然有一個用戶界面,無需等待Internet操作的慢速響應。
所以,考慮下面的代碼:
- (void)performSearch:(NSString *)term
{
NSLog(@"%s start: array has %d items", __FUNCTION__, [self.array count]);
// prepare to do search (the details here are not relevant)
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"http://search.twitter.com/search.json?q=%@", term]];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
// submit an Internet search that will be performed in the background
[NSURLConnection sendAsynchronousRequest:request
queue:queue
completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
// in the background, when the Twitter search is done,
// and when it's done, we'll make an array of the results
self.array = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
NSLog(@"%s: after background query, array now has %d items", __FUNCTION__, [self.array count]);
}];
// in the meantime, let's immediately carry on while that search is taking place
NSLog(@"%s end: array still has %d items", __FUNCTION__, [self.array count]);
}
這段代碼的細節都不是很重要,但其基本思想是,它是做一些緩慢(在因特網上執行一個Twitter搜索),但它會立即繼續在主線程中運行代碼,讓後臺線程按照自己的步調繼續運行。
各種NSLog
語句的時間戳是示出所有這些的定時:
2013-05-02 20:42:58.922 myapp[81642:c07] -[ViewController performSearch:] start: array has 0 items
2013-05-02 20:42:58.923 myapp[81642:c07] -[ViewController performSearch:] end: array still has 0 items
2013-05-02 20:42:59.798 myapp[81642:1303] __32-[ViewController performSearch:]_block_invoke: after background query, array now has 11 items
注意,經過之間的「開始」和「結束」的時間是大約1毫秒,但在完成的Twitter搜索在後臺花了幾乎整整一秒才完成。設計原則是,如果我們沒有異步執行此操作,在這種情況下使用completionHandler
,應用程序的用戶界面就會被凍結一秒鐘。但通過使用異步編程技術,該應用程序保持良好和響應,而是在後臺執行緩慢的操作。
我不熟悉setGroupWithName
方法,但它大概是執行相同類型的異步操作。因此,您嘗試查看後面緊跟的值將不會反映一旦該方法完成後將會更改的值(有點像我的示例中的「結束」NSLog語句不反映將發生的更改秒後)。
你的意思是,下次你遇到同樣的方法時,'s'應該有'something'。如果是這種情況,請將其聲明爲靜態。 – Mahesh 2013-05-02 20:52:31
沒有,當我離開塊時,'s'是零,就像它從未設置,目前 – Pittfall 2013-05-02 20:53:49
@Pittfall更可能,而不是_never_被設置,它的設置比你想象的晚,因爲'setGroupWithName'可能是一個緩慢的操作,在後臺異步運行。如果沒有看到這個方法的代碼或文檔,很難說,但它是來自'completionHandler'參數名稱的邏輯推理。 – Rob 2013-05-03 03:29:36