2015-11-29 29 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()),它会产生问题吗? –