不推荐使用iOS9 sendSynchronousRequest

24 ios swift

警告:在iOS 9.0中不推荐使用'sendSynchronousRequest(_:returningResponse :)':使用[NSURLSession dataTaskWithRequest:completionHandler:](参见NSURLSession)

urlData = try NSURLConnection.sendSynchronousRequest(request, returningResponse:&response)
Run Code Online (Sandbox Code Playgroud)

关于如何摆脱这种警告的任何想法?我刚刚从Swift 1.2升级到Swift 2

更新:Fonix被标记为我的最佳答案.如果您尝试添加try语句,我修改了他的答案如下:

urlData = try NSURLSession.dataTaskWithRequest(<#request: NSURLRequest#>, completionHandler: <#((NSData!, NSURLResponse!, NSError!) -> Void)?##(NSData!, NSURLResponse!, NSError!) -> Void#>)
Run Code Online (Sandbox Code Playgroud)

Nil*_*tel 39

使用NSURLSession如下,

对于Objective-C

NSURLSession *session = [NSURLSession sharedSession];
[[session dataTaskWithURL:[NSURL URLWithString:londonWeatherUrl]
          completionHandler:^(NSData *data,
                              NSURLResponse *response,
                              NSError *error) {
            // handle response

  }] resume];
Run Code Online (Sandbox Code Playgroud)

对于斯威夫特,

var request = NSMutableURLRequest(URL: NSURL(string: "YOUR URL"))
var session = NSURLSession.sharedSession()
request.HTTPMethod = "POST"

var params = ["username":"username", "password":"password"] as Dictionary<String, String>

var err: NSError?
request.HTTPBody = NSJSONSerialization.dataWithJSONObject(params, options: nil, error: &err)
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")

var task = session.dataTaskWithRequest(request, completionHandler: {data, response, error -> Void in
    println("Response: \(response)")})

task.resume()
Run Code Online (Sandbox Code Playgroud)

  • 但是语义是一样的吗?特别是,`sendSynchronousRequest`将阻止调用线程,直到收到响应,这有时正是你想要的.根据参考文档,`resume`将异步执行请求,这意味着它不能完全取代已弃用的功能. (29认同)
  • 这不是一个正确的答案,因为它不是同步的. (4认同)

Mik*_*nov 25

我为实际需要阻止当前线程执行的同步请求的情况编写了以下解决方案.我用这个迁移代码NSURLConnection,以NSURLSession在复杂的解决方案,这是一个相当麻烦,只是更改为异步方法.使用此解决方案,迁移只是方法名称替换.

注意:如果您的案例很简单,请使用接受的答案.

- (NSData *)sendSynchronousRequest:(NSURLRequest *)request returningResponse:(NSURLResponse **)response error:(NSError **)error
{

    NSError __block *err = NULL;
    NSData __block *data;
    BOOL __block reqProcessed = false;
    NSURLResponse __block *resp;

    [[[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData * _Nullable _data, NSURLResponse * _Nullable _response, NSError * _Nullable _error) {
        resp = _response;
        err = _error;
        data = _data;
        reqProcessed = true;
    }] resume];

    while (!reqProcessed) {
        [NSThread sleepForTimeInterval:0.02];
    }
    if (response != nil)
        *response = resp;
    if (error != nil)
        *error = err;
    return data;
}
Run Code Online (Sandbox Code Playgroud)

用法(简单替换NSURLConnection此方法):

//NSData *data = [NSURLConnection sendSynchronousRequest:theRequest returningResponse:&resp error:&err];
NSData *data = [self sendSynchronousRequest:theRequest returningResponse:&resp error:&err];
Run Code Online (Sandbox Code Playgroud)

  • 警告!这导致我们的应用程序出现了一些广泛的挂起/崩溃。我们的用户开始收到臭名昭著的“唤醒”日志。当他们的网络条件较差时就会发生这种情况。我没有修改该方法,我们暂时恢复为已弃用的方法。我可能建议 sleepForTimeInternal 至少为 20 毫秒。如果网络请求超时,0 将导致过度唤醒,并在请求响应时间过长时使用 100% CPU。 (3认同)

Nic*_*247 17

如果你需要阻止当前线程(比如Mike Keskinov的回答),最好使用gdc信号量而不是[NSThread sleepForTimeInterval:0].例如

dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
NSURLSession *session = [NSURLSession sharedSession];
[[session dataTaskWithURL:[NSURL URLWithString:londonWeatherUrl]
          completionHandler:^(NSData *data,
                              NSURLResponse *response,
                              NSError *error) {
            // handle response
            dispatch_semaphore_signal(semaphore);

  }] resume];

dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
Run Code Online (Sandbox Code Playgroud)


Hun*_*rDe 6

我已经稍微修改了Nilesh Patel的代码,因此您可以使用旧的调用,只需更改类名即可。

+ (NSData *)sendSynchronousRequest:(NSURLRequest *)request returningResponse:(NSURLResponse **)response error:(NSError **)error {
__block NSData *blockData = nil;
@try {

        __block NSURLResponse *blockResponse = nil;
        __block NSError *blockError = nil;

        dispatch_group_t group = dispatch_group_create();
        dispatch_group_enter(group);

        NSURLSession *session = [NSURLSession sharedSession];
        [[session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable subData, NSURLResponse * _Nullable subResponse, NSError * _Nullable subError) {

            blockData = subData;
            blockError = subError;
            blockResponse = subResponse;

            dispatch_group_leave(group);
        }] resume];

        dispatch_group_wait(group,  DISPATCH_TIME_FOREVER);

        *error = blockError;
        *response = blockResponse;

    } @catch (NSException *exception) {

        NSLog(@"%@", exception.description);
    } @finally {
        return blockData;
    }
}
Run Code Online (Sandbox Code Playgroud)