ios – 处理多个NSURL连接的最佳方式

前端之家收集整理的这篇文章主要介绍了ios – 处理多个NSURL连接的最佳方式前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我试图以编程方式创建一个xls表.为了填写表格,我在100左右制作了多个NSURLConnection.现在,我的方法是:

>建立连接并将数据存储到数组中.该数组有100个对象.
>现在取第一个对象并调用连接.存储数据.并在数组中与第二个对象建立第二个连接.这将持续到阵列中的最后一个对象.

完成100个连接平均需要14秒.有没有办法实现NSURLConnection以更快的方式获得响应?

直到昨天我遵循的基本方法如下:

声明属性

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

在viewDidLoad中初始化数组:

  1. reportArray=[[NSMutableArray alloc]init];

在按钮操作中初始化NSURLConnection:

  1. /initialize url that is going to be fetched.
  2. NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"****/%@/crash_reasons",ID]];
  3.  
  4. //initialize a request from url
  5. NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
  6. [request addValue:tokenReceived forHTTPHeaderField:@"**Token"];
  7.  
  8. [request setHTTPMethod:@"GET"];
  9. [request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
  10.  
  11. //initialize a connection from request
  12. self.getReportConnection = [[NSURLConnection alloc] initWithRequest:request delegate:self];

处理收到的数据:

  1. - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData*)data{
  2. if (connection==_getVersionConnection) {
  3.  
  4. [self.receivedData_ver appendData:data];
  5.  
  6. NSString *responseString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
  7.  
  8. NSError *e = nil;
  9. NSData *jsonData = [responseString dataUsingEncoding:NSUTF8StringEncoding];
  10.  
  11. NSDictionary *JSON = [NSJSONSerialization JSONObjectWithData:jsonData options: NSJSONReadingMutableContainers error: &e];
  12. [JSON[@"app_versions"] enumerateObjectsUsingBlock:^(id obj,NSUInteger idx,BOOL *stop) {
  13. if (![obj[@"id"] isEqual:[NSNull null]] && ![reportArray_ver containsObject:obj[@"id"]]) {
  14.  
  15. [reportArray_ver addObject:obj[@"id"]];
  16.  
  17. }
  18. NSLog(@"index = %lu,Object For title Key = %@",(unsigned long)idx,obj[@"id"]);
  19. }];
  20.  
  21. if (JSON!=nil) {
  22. UIAlertView *alert=[[UIAlertView alloc]initWithTitle:@"Version Reports succesfully retrieved" message:@"" delegate:self cancelButtonTitle:@"Ok" otherButtonTitles: nil];
  23. [alert show];
  24. }
  25. }
  26.  
  27. }

完成后调用另一个连接:

  1. // This method is used to process the data after connection has made successfully.
  2. - (void)connectionDidFinishLoading:(NSURLConnection *)connection{
  3. if (connection==getReportConnection) {
  4.  
  5. //check and call the connection again
  6. }
  7. }

今天,我尝试使用sendAsync的NSURLConnection一个接一个地使用循环触发所有连接,并且它工作得很好.

  1. self.receivedData_ver=[[NSMutableData alloc]init];
  2. __block NSInteger outstandingRequests = [reqArray count];
  3. for (NSString *URL in reqArray) {
  4.  
  5. NSMutableURLRequest *request=[NSMutableURLRequest requestWithURL:[NSURL URLWithString:URL]
  6. cachePolicy:NSURLRequestUseProtocolCachePolicy
  7. timeoutInterval:10.0];
  8.  
  9. [request setHTTPMethod:@"GET"];
  10. [request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
  11.  
  12.  
  13. [NSURLConnection sendAsynchronousRequest:request
  14. queue:[NSOperationQueue mainQueue]
  15. completionHandler:^(NSURLResponse *response,NSData *data,NSError *connectionError) {
  16.  
  17. [self.receivedData appendData:data]; //What is the use of appending NSdata into Nsmutable data?
  18.  
  19. NSString *responseString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
  20.  
  21. NSError *e = nil;
  22. NSData *jsonData = [responseString dataUsingEncoding:NSUTF8StringEncoding];
  23.  
  24. NSDictionary *JSON = [NSJSONSerialization JSONObjectWithData:jsonData options: NSJSONReadingMutableContainers error: &e];
  25. NSLog(@"login json is %@",JSON);
  26.  
  27. [JSON[@"app_versions"] enumerateObjectsUsingBlock:^(id obj,BOOL *stop) {
  28.  
  29.  
  30. if (![obj[@"id"] isEqual:[NSNull null]] && ![reportArray_ver containsObject:obj[@"id"]]) {
  31.  
  32. [reportArray_ver addObject:obj[@"id"]];
  33.  
  34. }
  35.  
  36. NSLog(@"index = %lu,obj[@"id"]);
  37. }];
  38.  
  39.  
  40. outstandingRequests--;
  41.  
  42. if (outstandingRequests == 0) {
  43. //all req are finished
  44. UIAlertView *alert=[[UIAlertView alloc]initWithTitle:@"Version Reports succesfully retrieved" message:@"" delegate:self cancelButtonTitle:@"Ok" otherButtonTitles: nil];
  45. [alert show];
  46. }
  47.  
  48. }];
  49. }

这次花了一半的时间来完成100个请求而不是旧的过程,除了asynReq之外还有更快的方法吗?.使用NSURLconnection和NSURLConnection与asyncReq的最佳方案是什么?

解决方法

几点意见:

>使用NSURLSession而不是NSURLConnection(如果您支持7.0及更高版本的iOS版本):

  1. for (NSString *URL in URLArray) {
  2. NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:URL];
  3.  
  4. // configure the request here
  5.  
  6. // now issue the request
  7.  
  8. NSURLSessionTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data,NSURLResponse *response,NSError *error) {
  9. // check error and/or handle response here
  10. }];
  11. [task resume];
  12. }

>如果您绝对必须发出100个请求,那么请像sendAsynchronousRequest实现(或我的dataTaskWithRequest)一样同时发出它们,而不是顺序发出.这就是实现巨大性能优势的原因.

但请注意,您无法保证它们完全按照您发布的顺序,因此您将需要使用一些支持它的结构(例如,使用NSMutableDictionary或使用占位符预填充NSMutableArray,以便您可以更新特定索引处的条目,而不是将项添加到数组中).

最重要的是,请注意它们可能无法按照要求完成相同的顺序,因此请确保妥善处理.
>如果您保留100个单独的请求,我建议您在非常慢的网络连接上进行测试(例如,使用网络链路调节器来模拟真正糟糕的网络连接;请参阅NSHipster discussion).只有在慢速连接时才会出现问题(超时,UI打嗝等).
>我建议使用调度组或操作队列依赖项,而不是减少待处理请求数的计数器.

  1. dispatch_group_t group = dispatch_group_create();
  2.  
  3. for (NSString *URL in URLArray) {
  4. dispatch_group_enter(group);
  5.  
  6. NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:URL];
  7.  
  8. // configure the request here
  9.  
  10. // now issue the request
  11.  
  12. NSURLSessionTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data,NSError *error) {
  13. // check error and/or handle response here
  14.  
  15. // when all done,leave group
  16.  
  17. dispatch_group_leave(group);
  18. }];
  19. [task resume];
  20. }
  21.  
  22. dispatch_group_notify(group,dispatch_get_main_queue(),^{
  23. // do whatever you want when all of the requests are done
  24. });

>如果可能,请查看是否可以重构Web服务,以便发出一个返回所有数据的请求.如果您正在寻求进一步的性能改进,那可能就是这样做的方式(并且它避免了在发出100个单独请求时涉及的许多复杂性).
>顺便说一句,如果您使用基于委托的连接,就像在原始问题中所做的那样,您不应该在didReceiveData中解析数据.这应该只是将数据附加到NSMutableData.在connectionDidFinishLoading委托方法中进行所有解析.

如果你去基于块的实现,这个问题就会消失,但只是观察你的代码片段.

猜你在找的iOS相关文章