2015-07-10 16 views
5

Tôi đang cố gắng tạo một bảng xls theo lập trình. Để điền vào trang tính, tôi đang tạo số nhiều NSURLConnection khoảng 100. Hiện tại, cách tiếp cận của tôi là:Cách tốt nhất để xử lý nhiều kết nối NSURL

  1. Tạo kết nối và lưu trữ dữ liệu vào một mảng. Mảng này có 100 đối tượng.
  2. Bây giờ lấy đối tượng đầu tiên và gọi kết nối. Lưu trữ dữ liệu. Và tạo kết nối thứ hai với đối tượng thứ 2 trong mảng. Điều này tiếp tục cho đến khi đối tượng cuối cùng trong mảng.

Mất trung bình 14 giây để hoàn thành 100 kết nối. Có cách nào để triển khai NSURLConnection để nhận phản hồi nhanh hơn không?

Đến ngày hôm qua tôi đi theo cách tiếp cận cơ bản như:

Tuyên bố các thuộc tính:

@property (nonatomic,strong) NSURLConnection *getReportConnection; 
@property (retain, nonatomic) NSMutableData *receivedData; 
@property (nonatomic,strong) NSMutableArray *reportArray; 

Khởi tạo mảng trong viewDidLoad:

reportArray=[[NSMutableArray alloc]init]; 

Khởi tạo các NSURLConnection trong một hành động nút:

/initialize url that is going to be fetched. 
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"****/%@/crash_reasons",ID]]; 

//initialize a request from url 
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; 
[request addValue:tokenReceived forHTTPHeaderField:@"**Token"]; 

[request setHTTPMethod:@"GET"]; 
[request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"]; 

//initialize a connection from request 
self.getReportConnection = [[NSURLConnection alloc] initWithRequest:request delegate:self]; 

Chế biến các dữ liệu nhận được:

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData*)data{ 
if (connection==_getVersionConnection) { 

    [self.receivedData_ver appendData:data]; 

    NSString *responseString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; 

    NSError *e = nil; 
    NSData *jsonData = [responseString dataUsingEncoding:NSUTF8StringEncoding]; 

    NSDictionary *JSON = [NSJSONSerialization JSONObjectWithData:jsonData options: NSJSONReadingMutableContainers error: &e]; 
    [JSON[@"app_versions"] enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { 
     if (![obj[@"id"] isEqual:[NSNull null]] && ![reportArray_ver containsObject:obj[@"id"]]) { 

      [reportArray_ver addObject:obj[@"id"]]; 

     } 
     NSLog(@"index = %lu, Object For title Key = %@", (unsigned long)idx, obj[@"id"]); 
    }]; 

    if (JSON!=nil) { 
     UIAlertView *alert=[[UIAlertView alloc]initWithTitle:@"Version Reports succesfully retrieved" message:@"" delegate:self cancelButtonTitle:@"Ok" otherButtonTitles: nil]; 
     [alert show]; 
    } 
} 

} 

Gọi một kết nối sau một kết thúc:

// This method is used to process the data after connection has made successfully. 
- (void)connectionDidFinishLoading:(NSURLConnection *)connection{ 
    if (connection==getReportConnection) { 

      //check and call the connection again 
    } 
} 

Và hôm nay, tôi đã thử NSURLConnection với sendAsync để bắn tất cả các kết nối một sau khi sử dụng vòng lặp khác và nó hoạt động khá tốt.

self.receivedData_ver=[[NSMutableData alloc]init]; 
__block NSInteger outstandingRequests = [reqArray count]; 
for (NSString *URL in reqArray) { 

    NSMutableURLRequest *request=[NSMutableURLRequest requestWithURL:[NSURL URLWithString:URL] 
                 cachePolicy:NSURLRequestUseProtocolCachePolicy 
                timeoutInterval:10.0]; 

    [request setHTTPMethod:@"GET"]; 
    [request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"]; 


[NSURLConnection sendAsynchronousRequest:request 
            queue:[NSOperationQueue mainQueue] 
         completionHandler:^(NSURLResponse *response, 
              NSData *data, 
              NSError *connectionError) { 

          [self.receivedData appendData:data]; //What is the use of appending NSdata into Nsmutable data? 

          NSString *responseString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; 

          NSError *e = nil; 
          NSData *jsonData = [responseString dataUsingEncoding:NSUTF8StringEncoding]; 

          NSDictionary *JSON = [NSJSONSerialization JSONObjectWithData:jsonData options: NSJSONReadingMutableContainers error: &e]; 
          NSLog(@"login json is %@",JSON); 

          [JSON[@"app_versions"] enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { 


           if (![obj[@"id"] isEqual:[NSNull null]] && ![reportArray_ver containsObject:obj[@"id"]]) { 

            [reportArray_ver addObject:obj[@"id"]]; 

           } 

           NSLog(@"index = %lu, Object For title Key = %@", (unsigned long)idx, obj[@"id"]); 
          }]; 


          outstandingRequests--; 

          if (outstandingRequests == 0) { 
           //all req are finished 
           UIAlertView *alert=[[UIAlertView alloc]initWithTitle:@"Version Reports succesfully retrieved" message:@"" delegate:self cancelButtonTitle:@"Ok" otherButtonTitles: nil]; 
           [alert show]; 
          } 

         }]; 
} 

Lần này phải mất một nửa thời gian để hoàn thành 100 yêu cầu hơn so với quy trình cũ, Có cách nào nhanh hơn tồn tại khác với asynReq? .What kịch bản tốt nhất để sử dụng NSURLconnectionNSURLConnection with asyncReq là?

+0

Tại sao không sử dụng NSURLSession? NSURLConnection hiện không được chấp nhận –

Trả lời

6

Một vài quan sát:

  1. Sử dụng NSURLSession hơn NSURLConnection (nếu bạn đang hỗ trợ các phiên bản iOS 7.0 và cao hơn):

    for (NSString *URL in URLArray) { 
        NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:URL]; 
    
        // configure the request here 
    
        // now issue the request 
    
        NSURLSessionTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { 
         // check error and/or handle response here 
        }]; 
        [task resume]; 
    } 
    
  2. Nếu bạn hoàn toàn phải ban hành 100 yêu cầu , sau đó phát hành đồng thời như triển khai sendAsynchronousRequest của bạn (hoặc dataTaskWithRequest) của tôi, không phải tuần tự. Đó là những gì đạt được lợi ích hiệu suất rất lớn. Tuy nhiên, lưu ý rằng bạn không có đảm bảo rằng chúng sẽ hoàn toàn theo thứ tự bạn đã phát hành, vì vậy bạn sẽ muốn sử dụng một số cấu trúc hỗ trợ (ví dụ: sử dụng NSMutableDictionary hoặc điền trước NSMutableArray với phần giữ chỗ để bạn chỉ có thể cập nhật mục nhập tại một chỉ mục cụ thể thay vì thêm một mục vào mảng).

    Dòng dưới cùng, lưu ý rằng chúng có thể không hoàn thành theo thứ tự như được yêu cầu, vì vậy hãy đảm bảo bạn xử lý điều đó một cách thích hợp.

  3. Nếu bạn giữ 100 yêu cầu riêng biệt, tôi khuyên bạn nên kiểm tra điều này trên kết nối mạng chậm (ví dụ: sử dụng Network Link Conditioner để mô phỏng kết nối mạng thực sự xấu; xem NSHipster discussion). Có vấn đề (thời gian chờ, trục trặc giao diện người dùng, v.v.) chỉ xuất hiện khi thực hiện điều này khi kết nối chậm.

  4. Thay vì giảm số lượt truy cập của số yêu cầu đang chờ xử lý, tôi khuyên bạn nên sử dụng nhóm công văn hoặc phụ thuộc hàng đợi hoạt động.

    dispatch_group_t group = dispatch_group_create(); 
    
    for (NSString *URL in URLArray) { 
        dispatch_group_enter(group); 
    
        NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:URL]; 
    
        // configure the request here 
    
        // now issue the request 
    
        NSURLSessionTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { 
         // check error and/or handle response here 
    
         // when all done, leave group 
    
         dispatch_group_leave(group); 
        }]; 
        [task resume]; 
    } 
    
    dispatch_group_notify(group, dispatch_get_main_queue(), ^{ 
        // do whatever you want when all of the requests are done 
    }); 
    
  5. Nếu có thể, xem bạn có thể cấu trúc lại các dịch vụ web, do đó bạn được phát hành một yêu cầu trả về tất cả các dữ liệu. Nếu bạn đang tìm kiếm cải thiện hiệu suất hơn nữa, đó có thể là cách để làm điều đó (và nó tránh được rất nhiều phức tạp liên quan khi phát hành 100 yêu cầu riêng biệt).

  6. BTW, nếu bạn sử dụng kết nối dựa trên đại biểu, như bạn đã làm trong câu hỏi ban đầu, bạn nên không là phân tích dữ liệu trong didReceiveData. Điều đó chỉ nên được thêm dữ liệu vào một số NSMutableData. Thực hiện tất cả phân tích cú pháp trong connectionDidFinishLoading phương thức ủy quyền.

    Nếu bạn chuyển sang triển khai dựa trên khối, sự cố này sẽ biến mất, nhưng chỉ quan sát trên đoạn mã của bạn.

+0

@ Rob- Tôi đã thử đặt phiên url trong vòng lặp nhưng, nó không được thực thi. Bằng cách nào đó, khối mã bên trong phiên url đang bị bỏ qua. – ZeeroCool77

+0

@ T_77 - Vâng, sau đó thực hiện một số chẩn đoán cơ bản với báo cáo nhật ký hoặc điểm ngắt, đảm bảo rằng bạn nhấn vào dòng 'resume' giống như bạn cần. Nhưng mô hình này để sử dụng 'NSURLSession' là khá chuẩn, vì vậy tôi nghi ngờ vấn đề là không liên quan. Các yêu cầu có bắt đầu chính xác không? Hãy thử xem các yêu cầu bằng cách sử dụng [Charles] (http://charlesproxy.com). – Rob

+0

@ Rob-nó hoạt động. Tôi có thể upvote câu trả lời của bạn quá, nhưng xin lỗi mà tôi không có đủ rep !!! Cảm ơn câu trả lời gr8. – ZeeroCool77

1

Sử dụng sendAsynchronous là một cách tuyệt vời để cải thiện tổ chức mã. Tôi chắc chắn với một số giám sát cẩn thận, chúng tôi có thể cải thiện tốc độ ở lề, nhưng cách để cải thiện đáng kể tốc độ là không thực hiện 100 yêu cầu.

Nếu nội dung phản hồi nhỏ, hãy tạo điểm cuối trả lời kết hợp của kết quả.

Nếu nội dung phản hồi lớn, thì bạn đang yêu cầu nhiều dữ liệu hơn so với nhu cầu của người dùng vào lúc này. Chỉ giữ giao diện người dùng trên những gì người dùng cần xem và nhận phần còn lại âm thầm (... hoặc, có thể tốt hơn âm thầm, lười biếng).

Nếu bạn không kiểm soát máy chủ và các cơ quan phản hồi nhỏ và người dùng cần tất cả hoặc hầu hết để tiếp tục với ứng dụng thì bạn có thể bắt đầu thực hiện hiệu suất ở lề và giao diện người dùng để giải trí người dùng trong khi ứng dụng hoạt động, nhưng thường là một trong những hạn chế đó - thường là ứng dụng sau - có thể thoải mái.

+0

Trong khi tạo kết nối, tôi chỉ hiển thị thanh tiến trình và xóa nó sau khi kết nối được thực hiện. – ZeeroCool77

Các vấn đề liên quan