首先,讓我說我強烈阻止這樣做。您的主線程正在等待,在等待呼叫完成時什麼都不做。在某些情況下,如果系統沒有在主線程上響應,系統會終止您的應用。這非常不尋常。
我想你應該是決定何時/如何使用各種編程工具的人。
這一個完全是你想要的...阻塞主線程,直到完成處理程序運行。同樣,我不建議這樣做,但是,嘿,這是一個工具,我會好好NRA立場:槍不殺人...
__block BOOL waitingOnCompletionHandler = YES;
[object doSomethingWithCompletionHandler:^{
// Do your work in the completion handler block and when done...
waitingOnCompletionHandler = NO;
}];
while (waitingOnCompletionHandler) {
usleep(USEC_PER_SEC/10);
}
另一種選擇是執行run循環。但是,這並不是真正的同步,因爲運行循環實際上會處理其他事件。我在一些單元測試中使用了這種技術。它與上面類似,但仍然允許其他內容在主線程上發生(例如,完成處理程序可能會調用主隊列上的操作,這可能無法在前一個方法中執行)。
__block BOOL waitingOnCompletionHandler = YES;
[object doSomethingWithCompletionHandler:^{
// Do your work in the completion handler block and when done...
waitingOnCompletionHandler = NO;
}];
while (waitingOnCompletionHandler) {
NSDate *futureTime = [NSDate dateWithTimeIntervalSinceNow:0.1];
[[NSRunLoop currentRunLoop] runUntilDate:futureTime];
}
還有其他的方法爲好,但這些都是很簡單,易於理解,並伸出像突兀,所以很容易知道你是標新立異。
我還應該注意,我從來沒有遇到過很好的理由在測試以外的任何事情上做到這一點。你可以死鎖你的代碼,而不是從主運行循環返回是一個滑坡(即使你自己手動執行它 - 請注意,稱爲你的東西仍在等待,再次運行該循環可能會重新輸入該代碼,或導致一些其他問題)。
異步API很棒。條件變量方法或對併發隊列使用屏障是在使用其他線程時進行同步的合理方法。同步主線程與您應該做的事情相反。
祝你好運...並確保你註冊你的槍,並始終攜帶你隱藏的武器許可證。這當然是狂野的西部。總是有一個約翰韋斯利哈登在那裏尋找槍戰。
...謝謝你的時間。我試圖搜索沒有塊的舊API開放文檔。任何想法,這是如何實現的? – 2012-05-08 11:02:22
UIManagedDocument是一個相對較新的接口,我不認爲它有過同步API。在內部,它有兩個ManagedObjectContext對象...一個在主線程中,一個使用私有調度隊列。所有IO操作都發生在後臺,所以類的性質決定了使用異步API。在塊之前,異步API使用委託或通知讓調用者知道操作何時完成。 – 2012-05-08 12:36:53
這不行,當我嘗試下面的代碼: __block BOOL waitingOnCompletionHandler = YES;如果(成功)DLog(@「open document succeed!」);如果(成功){0} self.managedObjectContext = _managedDocument.managedObjectContext; waitingOnCompletionHandler = NO; } }];同時(waitingOnCompletionHandler)使用USLE_PER_SEC/10; } 主線程永遠卡在那裏... – zolibra 2013-06-27 01:22:41