2015-11-29 27 views
1

我是Objective C的初學者,我正在尋找兩個連續的HTTP GET(一個接一個)。到目前爲止我所擁有的是在第一個NSURLSessionDataTask的完成塊內部有一個NSURLSessionDataTask。這導致我的代碼有點不可讀,所以我想知道什麼是更好的方法來做到這一點? 下面是一些示例代碼:爲兩個連續HTTP GET嵌套NSURLSessionDataTask

{ 
    NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];  
    NSURLSession *session = [NSURLSession sessionWithConfiguration:config]; 

    NSMutableURLRequest *url_request_1 = [NSMutableURLRequest requestWithURL:@"some_url_1"]; 
    [url_request_1 setHTTPMethod:@"GET"]; 

    NSURLSessionDataTask *url_task_1 = [session 
     dataTaskWithRequest:url_request_1 
     completionHandler:^(NSData *data1, 
     NSURLResponse *response1, 
     NSError *error1) { 

      if(data1 !=nil){ 
       // Evaluate some_url_2 from the response of url_task_1 

       NSMutableURLRequest *url_request_2 = [NSMutableURLRequest requestWithURL:@"some_url_2"]; 
       [url_request_2 setHTTPMethod:@"GET"]; 

       NSURLSessionDataTask *url_task_2 = [session 
        dataTaskWithRequest:url_request_2 
        completionHandler:^(NSData *data2, 
        NSURLResponse *response2, 
        NSError *error2) { 

         if(data2 !=nil){  
          // Process data here     
         } else { 
          // Handle error here. 
          return; 
         } 
        }]; 

       [urlRequest2 resume]; 
      } 
      else{ 
       // Handle error here 
       return; 
      } 
     }]; 

    [url_task_1 resume]; 
} 
+0

@Velox - 手動改變問題的縮進可能使它更具可讀性,但你現在正在模糊Tywin如何編寫他的代碼的一個基本問題。 – Rob

回答

1

這是由少一點笨拙通過改變你的縮進風格,並使用早射圖案。

- (void)performRequestsWithCompletion:(void (^ _Nonnull)(NSDictionary *, NSError *))completion { 
    NSMutableURLRequest *request1 = [NSMutableURLRequest requestWithURL:firstURL]; 

    NSURLSessionDataTask *task1 = [self.session dataTaskWithRequest:request1 completionHandler:^(NSData *data1, NSURLResponse *response1, NSError *error1) { 
     if (!data1) { 
      // handle error here, then return 
      completion(nil, error1); 
      return; 
     } 

     NSMutableURLRequest *request2 = [NSMutableURLRequest requestWithURL:secondURL]; 

     NSURLSessionDataTask *task2 = [self.session dataTaskWithRequest:request2 completionHandler:^(NSData *data2, NSURLResponse *response2, NSError *error2) { 
      if (!data2) { 
       // handle error here, then return 
       completion(nil, error2); 
       return; 
      } 

      // handle parsing `data2` here 
      NSDictionary *result = ...; 
      completion(result, nil); 
     }]; 

     [task2 resume]; 
    }]; 

    [task1 resume]; 
} 

注意,我在這裏補充完成處理程序,因爲這是讓最好的模式無論提出的要求,一切都進行的一個。顯然,我的塊參數假設你會返回一個字典,所以你應該改變它爲你的例程返回的任何類型。

或者(特別是如果你正在做的不僅僅是兩個連續的Web服務調用更多),你可以將其分爲不同的方法:

- (void)performRequestsWithCompletion:(void (^ _Nonnull)(NSDictionary *, NSError *))completion { 
    [self performFirstRequestWithCompletion:completion]; 
} 

- (NSURLSessionTask *)performFirstRequestWithCompletion:(void (^ _Nonnull)(NSDictionary *, NSError *))completion { 
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:firstURL]; 

    NSURLSessionTask *task = [self.session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { 
     if (!data || error) { 
      // Handle error here 
      completion(nil, error); 
      return; 
     } 

     // Evaluate some_url_2 from the response of url_task_1 
     [self performSecondRequestWithCompletion:completion]; 
    }]; 
    [task resume]; 

    return task; 
} 

- (NSURLSessionTask *)performSecondRequestWithCompletion:(void (^ _Nonnull)(NSDictionary *, NSError *))completion { 
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:secondURL]; 

    NSURLSessionTask *task = [self.session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { 
     if (!data || error) { 
      // Handle error here, and return 
      completion(nil, error); 
      return; 
     } 

     // Process data here 

     NSDictionary *result = ...; 
     completion(result, nil); 
    }]; 

    [task resume]; 

    return task; 
} 

有了這種模式,無論有多少依賴打電話給你,你不會結束嵌套塊的塔。


在完整性的利益,即避免這些塔等圖案塊中之塊包括NSOperation圖案和第三方接近像期貨/承諾(例如PromiseKit)。這些超出了這個問題的範圍,但是如果你這麼做的話,他們值得考慮。

+0

好吧,我想把它分解成不同的方法會更有意義。希望這是很好的做法。感謝Rob! – Tywin

+0

@Tywin - 無需感謝。請參閱[我應該怎麼做當有人回答我的問題?](http://stackoverflow.com/help/someone-answers) – Rob

+0

我更喜歡你的第二個場景。用兩種不同的方法打破兩項任務是很好的。如果我在NSURLSessionDataTask中添加dispatch_async(dispatch_get_main_queue()),它會產生問題嗎? –