2016-05-25 25 views
1

同步NSURLConnection的作爲最佳實踐,以取代NSURLSession

NSURLConnection sendSynchronousRequest:returningResponse:error:&connectionError 

是集棄用我將不得不更換一個進口商,我寫了很久以前。

導入器執行以下操作:

  1. 它獲取從API-A的數據。數據可以在多個頁面上。
  2. 它使用從第一數據提取(也多頁)來查詢從API-B數據和合並
  3. 結果從API-B的查詢將與數據從API-A

我被合併通過後臺操作實現了這一點,其中我使用每個API的方法,如果請求有多個頁面,則遞歸調用。

但是由於NSURLSession不支持同步請求,我目前只能看到有很多開銷(例如iVars)控制完成塊(例如下一頁或開始查詢API-B)的內容的選項。

那麼,什麼是一個優雅的解決方案,把這個NSURLSession。

注:只是爲了確保,我以前的解決方案根本不會阻塞主線程。但當時,這是控制兩個來源合併的最簡單方法。

+0

這裏是你的答案,http://stackoverflow.com/a/30952732/2713079 – itsji10dra

+1

我不明白這就是爲什麼你需要同步調用。由於按正常慣例,Webservicecalls始終應該是異步的。如果你想讓用戶等待,那麼..把一個HUD/ActivityIndi​​cator顯示設備正在獲取結果..同步調用任何web api不是一個好主意。所以按照我的建議去通過異步調用 –

+1

正如我上面提到的,我在後臺線程上進行導入,所以既沒有阻塞UI也沒有一些進度指示器可見。 而我之所以使用同步方法(同樣,我用它的方式並沒有阻止任何東西!)是我必須等待來自未知數量請求的未知數量的數據。而且,同步方法允許我處理這個問題比保留處理異步請求的大量開銷要好得多。 – MatzeLoCal

回答

3

這個答案不應該是最佳實踐。這對我來說很實際。

時同步請求的一堆在後臺執行和執行事項的順序我已經結束了使用以下與形勢:

SyncRequestSender.h

#import <Foundation/Foundation.h> 

@interface SyncRequestSender : NSObject 

+ (NSData *)sendSynchronousRequest:(NSURLRequest *)request 
       returningResponse:(NSURLResponse **)response 
          error:(NSError **)error; 

@end 

SyncRequestSender.m

#import "SyncRequestSender.h" 

@implementation SyncRequestSender 

+ (NSData *)sendSynchronousRequest:(NSURLRequest *)request 
       returningResponse:(NSURLResponse **)response 
          error:(NSError **)error 
{ 
    dispatch_group_t group = dispatch_group_create(); 
    dispatch_group_enter(group); 


    NSError __block *err = NULL; 
    NSData __block *data; 
    NSURLResponse __block *resp; 

    [[[NSURLSession sharedSession] dataTaskWithRequest:request 
            completionHandler:^(NSData* _data, NSURLResponse* _response, NSError* _error) { 
     resp = _response; 
     err = _error; 
     data = _data; 
     dispatch_group_leave(group); 

    }] resume]; 

    dispatch_group_wait(group, DISPATCH_TIME_FOREVER); 

    if (response) 
    { 
     *response = resp; 
    } 
    if (error) 
    { 
     *error = err; 
    } 

    return data; 
} 

@end 
+0

使用'dispatch_semaphore_wait'更好,我想。 –

+0

@KleinMioke考慮使用它,但由於某種原因決定與派遣組一起玩。 – Anton

2

這是AFNetworking中的一個示例,它顯示瞭如何等待異步任務。

- (NSArray *)tasksForKeyPath:(NSString *)keyPath { 
    __block NSArray *tasks = nil; 
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); 
    [self.session getTasksWithCompletionHandler:^(NSArray *dataTasks, NSArray *uploadTasks, NSArray *downloadTasks) { 
     if ([keyPath isEqualToString:NSStringFromSelector(@selector(dataTasks))]) { 
      tasks = dataTasks; 
     } else if ([keyPath isEqualToString:NSStringFromSelector(@selector(uploadTasks))]) { 
      tasks = uploadTasks; 
     } else if ([keyPath isEqualToString:NSStringFromSelector(@selector(downloadTasks))]) { 
      tasks = downloadTasks; 
     } else if ([keyPath isEqualToString:NSStringFromSelector(@selector(tasks))]) { 
      tasks = [@[dataTasks, uploadTasks, downloadTasks] valueForKeyPath:@"@unionOfArrays.self"]; 
     } 

     dispatch_semaphore_signal(semaphore); 
    }]; 

    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); 

    return tasks; 
}