使用NSURLSession替换同步NSURLConnection的最佳实践

时间:2016-05-25 08:17:05

标签: ios nsurlconnection nsurlsession

作为

db.contacts.mapReduce(
  function(){
    numbers = [];
    value={phone:this.<<called_number>>};
    numbers.push(value);
    emit(this.<<caller_number>>,{called:numbers});
  },
  function(key,values) {
    result={called:[]};
    values.forEach(function (v) {
      var i,j;
      for(i=0;i<v.called.length;i++) {
        var flag=0;
        for(j=0;j<result.called.length;j++) {
          if(v.called[i].phone==result.called[j].phone){
            flag=1;
          }
        }
        if(flag==0) {
          result.called.push(v.called[i])
        }
      }
    });
    return result;
  },
  {"query": {},"out":"new_collection"}
)

设置已弃用我将不得不替换我很久以前写过的导入器。

导入器执行以下操作:

  1. 从API-A获取数据。那里的数据可以在多个页面上。
  2. 它使用来自第一次获取(也是多页)的数据来查询来自API-B的数据并合并
  3. API-B查询的结果将与API-A
  4. 中的数据合并

    我使用后台操作实现了这一点,其中我使用每个API的方法,如果请求有多个页面,则递归调用。

    但是由于NSURLSession不支持同步请求,我目前只看到有很多开销的选项(例如iVars)控制在完成块中调用的内容(例如,下一页或开始查询API-B)。

    那么,将这个纳入NSURLSession是一个优雅的解决方案。

    注意:为了确保,我以前的解决方案根本不会阻止主线程。但那时候它是控制两个来源合并的最简单方法。

2 个答案:

答案 0 :(得分:5)

这个答案不应该是最佳做法。这对我来说很实用。

面对在后台执行一堆同步请求并且执行顺序问题的情况,我最终使用了以下内容:

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

答案 1 :(得分:3)

这是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;
}