2011-12-14 125 views
2

我正在重寫回調方法以處理HTTP請求的響應。如何使異步調用同步

-(NSObject<HTTPResponse> *)httpResponseForMethod:(NSString *)method URI:(NSString *)path{ 
    NSObject <HTTPResponse> *response; 
    // Here I should load the data 
} 

然而,在我的要求我必須加載一些數據只能異步:

- (void)assetForURL:(NSURL *)assetURL resultBlock:(ALAssetsLibraryAssetForURLResultBlock)resultBlock failureBlock:(ALAssetsLibraryAccessFailureBlock)failureBlock; 

由於我在synchonous方法,我不能「離開」的方法之前,我有數據。此外,我無法預先加載所需的數據,因爲我不知道需要哪些資產,直到我處於請求中。

這似乎是一個相當棘手的設計問題,我看不到一個解決方案如何解決這個問題,沒有一些主要的黑客。

+2

您可以更改強制您的HTTP請求同步的對象嗎? HTTP請求不應該是同步的。 如果你不能這樣做,而且你真的必須解決這個問題,你可以創建並運行一個運行循環,直到請求完成。但我認爲這屬於你(正確)想要避免的「主要黑客」類別。 – stevex 2011-12-14 15:28:17

回答

5

編輯:stevex是絕對正確的,你的第一優先權應該是找到一種方式,使整個事情異步。否則,下面的答案應該在將同步步驟委託給操作系統以實現最佳用電時達到您想要的效果。

也許你想用一個NSConditionLock鎖定呼叫後立即調用assetForUrl:...的東西,然後讓你的回調將它解鎖。

條件鎖是一個條件鎖。所以你說'當條件是X時我想要鎖',並且你的線程阻塞,直到它處於這種狀態。然後,您可以獲得鎖定,直到您解鎖它,並且您可以指定在解鎖後立即處於什麼狀態。

使用NSIntegers指定條件;

所以有鎖通信內置的一個方面。

因此,舉例來說:

NSConditionLock *conditionLock; // somewhere; an instance variable 

#define kYourClassInitialCondition 0 
#define kYourClassWaitingCondition 1 
// etc 

... 

[conditionLock lockWhenCondition:kYourClassInitialCondition]; 

[whomever assetForUrl:whatever 
      resultBlock:^(args here) 
         { 
         ... do relevant immediate work here ... 

         [conditionLock lockWhenCondition:kYourClassWaitingCondition]; 
         [conditionLock unlockWithCondition:kYourClassFinishedCondition]; 
         } 
      failureBlock:^(args here) 
         { 
         ... as above, same semantics when done ... 
         } 
]; 


[conditionLock unlockWithCondition:kYourClassWaitingCondition]; 

[conditionLock lockWhenCondition:kYourClassFinishedCondition]; 
[conditionLock unlockWithCondition:kYourClassInitialCondition]; 

所以,調用線程上的邏輯是:

  • 獲取初始條件鎖
  • 問題的URL獲取請求
  • 發佈處於等待狀態的鎖
  • 獲得完成狀態的鎖
  • 在初始條件下

和邏輯上的結果塊釋放鎖是:

  • 獲取鎖在等待狀態
  • 釋放完成的狀態中的鎖定

結果塊將阻塞,直到調用線程將條件鎖定置於等待狀態。所以如果回調是立即的,那麼順序沒有問題。

建立等待條件後,調用線程將會阻塞,直到條件鎖定在完成條件釋放。所以如果還沒有完成,它應該等待結果塊完成。

這當然假設您的結果塊是由被調用者通過GCD調度的,或者是如果從單獨的線程調用內聯調用。前者可能是一個安全的假設。