2013-04-11 57 views
2

我有一個在後臺線程上調用的方法foo:。此方法只是向服務器發送請求,並在檢索數據後對這些數據執行一些計算並返回。在這種情況下,我更喜歡使用sendSynchronousRequest:因爲此方法很方便,並且線程是否被阻塞並不重要。但是,該響應包含一個「位置」標題字段,該字段將重定向到另一個頁面。我想讀取響應以在重定向之前獲取這些「Set-Cookie」標題字段。看來,同步方法不允許我。如何在後臺線程上執行異步請求?

我試圖使用異步的並實現NSURLConnectionDataDelegate,但線程完成之前調用委託的這些方法。 (我想蘋果公司實現異步操作的方式是在新線程上執行那些耗時的工作)

有什麼辦法可以解決這個問題嗎?由於在主線程上執行異步請求可能會增加我的程序的複雜性。

foo的:方法是一種像這樣

- (Result *)foo 
{ 
    NSURLMutableRequest * request = blablabla; 
    //Do something to initialize the request 
    NSData *data = [NSURLConnection sendSynchronousRequest:request 
             returningResponse:&response 
                error:&error]; 

    //Do something with the data 

    Result *result = [[Result alloc] init] autorelease]; 
    //fill the result 

    return result; 
} 
+0

不確定爲什麼您認爲在主線程上執行異步請求可能會增加程序的複雜性。創建後臺線程通常只有在您需要執行長時間或計算密集型任務時纔有意義,因爲線程很快完成,這似乎不是這種情況。 – 2013-04-11 07:45:38

+0

正如你所提到的,foo方法是一個在計算密集型任務中調用的中間方法,我覺得它應該不在主線程中執行。 – Poligun 2013-04-11 08:22:37

回答

3

你可以使用一個大中央調度信號等到異步請求返回:

- (Result *)foo 
{ 
    NSMutableURLRequest * request = [[NSMutableURLRequest alloc] init]; 
    // set request's properties here 

    __block Result *result; 
    dispatch_semaphore_t holdOn = dispatch_semaphore_create(0); 
    [NSURLConnection sendAsynchronousRequest:request queue:[[NSOperationQueue alloc] init] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) { 
     if (error) 
     { 
      // handle error 
     } 
     else 
     { 
      result = [[Result alloc] initWithData:data]; 
     } 
     dispatch_semaphore_signal(holdOn); 
    }]; 

    dispatch_semaphore_wait(holdOn, DISPATCH_TIME_FOREVER); 

    return result; 
} 

注:此代碼需要iOS 4.0+和ARC!

0

您可以創建自己的NSRunLoop,做你的要求有。完成請求後停止運行循環。

或者如果你是懶惰和我一樣,不想與運行循環的一塌糊塗,只是把主線程的連接:

dispatch_async(dispatch_get_main_queue(), ^(void){ 
    self.connection = [[NSURLConnection alloc] initWithRequest:request delegate:self]; 
    [connection start]; 
} 
0

你可以找到一個小而簡單的課程,讓你在github上做到這一點。它提供了兩個主要對象 - 設計用於運行後臺提取的NSOperationsQueue管理器和NSOperation子類。如前所述,如果你所做的只是獲取,你可以在主線程上做到這一點。但是如果你也想做數據處理,那麼這個項目會讓你在完成的方法中做到這一點。

OperationsRunner類的一個不錯的屬性是您可以隨時取消操作(例如用戶點擊後退按鈕),並且所有內容都快速拆除,不會發生拖延或泄漏。然而,如果你所做的只是這一個獲取和一個進程,那麼你可以像其他人說的那樣只是獲取主線程中的數據,一旦你擁有了它,然後將一個「處理」塊分派到其中一個併發系統線程,以及處理完成後,向主線程發送另一條消息,告訴您工作已完成。

相關問題