简体   繁体   English

iOS9 sendSynchronousRequest已弃用

[英]iOS9 sendSynchronousRequest deprecated

Warning:'sendSynchronousRequest(_:returningResponse:)' was deprecated in iOS 9.0: Use [NSURLSession dataTaskWithRequest:completionHandler:] (see NSURLSession) 警告:'sendSynchronousRequest(_:returningResponse :)'已在iOS 9.0中弃用:使用[NSURLSession dataTaskWithRequest:completionHandler:](请参阅NSURLSession)

urlData = try NSURLConnection.sendSynchronousRequest(request, returningResponse:&response)

Any idea on how to get rid of this warning? 关于如何消除此警告的任何想法? I just upgraded from Swift 1.2 to Swift 2 我刚刚从Swift 1.2升级到Swift 2

UPDATE: Fonix is marked as my best answer. 更新:Fonix被标记为我最好的答案。 If your trying to add a try statement, I modified his answer as followed: 如果您尝试添加try语句,我将其答案修改如下:

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

Use NSURLSession instead like below, 改为使用NSURLSession如下所示,

For Objective-C 对于Objective-C

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

  }] resume];

For Swift, 对于Swift,

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()

I wrote the following solution for the cases when you actually need for synchronous request which blocks the current thread execution. 当您实际需要阻止当前线程执行的同步请求时,我写了以下解决方案。 I use this code for migration from NSURLConnection to NSURLSession in the complex solution where it was quite a hassle to just change to async approach. 我使用此代码在复杂的解决方案中从NSURLConnection迁移到NSURLSession ,而只需更改为异步方法就很麻烦了。 With this solution the migration is just method name replacement. 使用此解决方案,迁移仅是方法名称的替换。

NOTE: If you have a simple case, please use the accepted answer instead. 注意:如果您的情况很简单,请改用已接受的答案。

- (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;
}

Usage (simple replace NSURLConnection to this method): 用法(将此方法简单替换为NSURLConnection ):

//NSData *data = [NSURLConnection sendSynchronousRequest:theRequest returningResponse:&resp error:&err];
NSData *data = [self sendSynchronousRequest:theRequest returningResponse:&resp error:&err];

If you need to block the current thread (like Mike Keskinov's answer), best to use gdc semaphore instead of doing a [NSThread sleepForTimeInterval:0]. 如果您需要阻止当前线程(例如Mike Keskinov的答案),最好使用gdc信号灯,而不要执行[NSThread sleepForTimeInterval:0]。 eg 例如

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);

and Swift (tested on 5.0): 和Swift(在5.0上测试):

let semaphore = DispatchSemaphore(value:0)

URLSession.shared.dataTask(with: serverUrl) { (httpData, response, error) in
    // handle response
    semaphore.signal()
}.resume()

semaphore.wait()

I have modified the code of Nilesh Patel a little bit, so you can use the old call, just by changing class name. 我已经稍微修改了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;
    }
}

Swift 4 / Xcode 9 Swift 4 / Xcode 9

If you really want the request to be synchronous like in the deprecated semantics, you can block the main thread with an empty loop on a condition set true by the completion handler: 如果您确实希望请求像不赞成使用的语义那样是同步的,则可以在完成处理程序设置为true的条件下使用空循环来阻塞主线程:

let request = URLRequest(url: URL(string: "YOUR_URL")!)
let session = URLSession.shared
var gotResp = false

let task = session.dataTask(with: request,
            completionHandler: { data, response, error -> Void in
                // do my thing...
                gotResp = true
            })
task.resume()

// block thread until completion handler is called
while !gotResp {
    // wait
}

print("Got response in main thread")
...

EDIT: or if you prefer to use semaphores like in the Obj-C Nick H247 answer: 编辑:或如果您更喜欢使用Obj-C Nick H247答案中的信号量:

let request = URLRequest(url: URL(string: "YOUR_URL")!)
let session = URLSession.shared
let ds = DispatchSemaphore( value: 0 )    
let task = session.dataTask(with: request,
            completionHandler: { data, response, error -> Void in
                // do my thing..., then unblock main thread
                ds.signal()
            })
task.resume()

// block thread until semaphore is signaled
ds.wait()

print("Got response in main thread")
...

you can hide that warning in your project by using following code write your method between input directives and your warning goes away. 您可以使用以下代码在输入指令之间编写方法,从而在项目中隐藏该警告,然后警告消失。

#pragma GCC diagnostic push 
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
- (void)yourMethodToCallNSURLConnection {
//use deprecated stuff
}
#pragma GCC diagnostic pop

Here is a complete version of mine with dispatch_semaphore_t and return response and error without block assign warning . 这是我的完整版本,带有dispatch_semaphore_t,并且返回响应和错误,而没有块分配警告。 Thank @Nick H247 and @Mike Keskinov. 感谢@Nick H247和@Mike Keskinov。

- (NSData*)sendSynchronousRequest:NSURLRequest *urlRequest
                returningResponse:(NSURLResponse **)outResponse
                            error:(NSError **)outError
{

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

//    data = [NSURLConnection sendSynchronousRequest:urlRequest returningResponse:response error:error];

    dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
    NSURLSession *session = _session;
    [[session dataTaskWithRequest:urlRequest
            completionHandler:^(NSData *_data,
                                NSURLResponse *_response,
                                NSError *_error) {
                // handle response
                data = _data;
                resp = _response;
                err = _error;

                reqProcessed = true;

                dispatch_semaphore_signal(semaphore);

            }] resume];

    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);

    if (reqProcessed) {
        if(outResponse != NULL) {
            *outResponse = resp;
        }

        if (outError != NULL) {
            *outError = err;
        }

    }

    return data;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM