使用 NSURLSession 等待 HTTP 请求的响应 - Objective C

Wait response for HTTP request using NSURLSession - Objective C

现在我正在开发我的小 class,它有一个发送 POST 请求的方法。此方法用于 returning ResponseModel(基本上有两个 ivars:代码、消息),此模型将从响应映射。 我正在使用 dataTaskWithRequest:urlRequest completionHandler: 方法。像这样:

+ (void)sendPOSTRequest1:(id)data withResponse:(void (^) (ResponseModel * data) )taskResponse {
    NSError *error = nil;

    NSMutableURLRequest * urlRequest = [self getRequestObject];

    [urlRequest setHTTPMethod:@"POST"];

    NSData * requestData = [self encodeAndEncrypt:data];

    [urlRequest setHTTPBody:requestData];


    NSURLSession *session = [NSURLSession sharedSession];
    NSURLSessionDataTask *dataTask = [session
                                      dataTaskWithRequest:urlRequest
                                      completionHandler:
                                      ^(NSData *data, NSURLResponse *response, NSError *error) {

        NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;

        ResponseModel * responseModel = [NSKeyedUnarchiver
                                         unarchivedObjectOfClass:[ResponseModel class]
                                         fromData:data
                                         error:&error];

        taskResponse(responseModel);


    }];

    [dataTask resume];
}

并这样调用方法:

DummyModel * dummy = [[DummyModel alloc] init];

__block ResponseModel * result = [[ResponseModel alloc] init];

[HTTPRequest sendPOSTRequest1:dummy withResponse:^(ResponseModel *data) {
    result =  data;
    NSLog(@"data %@",data);
}];

// It`s not sure that the asyncronous request has already finished by this point
NSLog(@"POST result : %@",result);

我的问题是我不想在回调块中执行代码,因为我需要等待响应才能 return 一个 ResponseModel 并且实现它的任何人都可以接收模型并制作其他的东西。 我一直在研究使用 NSURLConnection,因为它有一个执行同步请求的方法,但现在它已被弃用,所以我想知道:这是一种我可以使用代码中的内容等待响应的方法吗?

您可以使用 GCD 实现这样的同步请求:

swift代码

public static func requestSynchronousData(request: URLRequest) -> Data? {
    var data: Data? = nil
    let semaphore: DispatchSemaphore = DispatchSemaphore(value: 0)
    let task = URLSession.shared.dataTask(with: request, completionHandler: {
        taskData, _, error -> () in
        data = taskData
        if data == nil, let error = error {print(error)}
        semaphore.signal()
    })
    task.resume()
    _ = semaphore.wait(timeout: .distantFuture)
    return data
}

Objective-C代码

+ (NSData *)requestSynchronousData:(NSURLRequest *)request {
    __block NSData * data = nil;
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
    NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData * _Nullable taskData, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        if (error) {
            NSLog(@"%@", error);
        }
        data = taskData;
        dispatch_semaphore_signal(semaphore);
    }];
    [task resume];
    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
    return data;
}

您可以使用dispatch_async来处理UI块内的交互

DummyModel * dummy = [[DummyModel alloc] init];

__block ResponseModel * result = [[ResponseModel alloc] init];

[HTTPRequest sendPOSTRequest1:dummy withResponse:^(ResponseModel *data) {
    result =  data;
    dispatch_async(dispatch_get_main_queue(), ^{
       // handle some ui interaction
    });
    NSLog(@"data %@",data);
}];