ios 不推荐使用 iOS9 sendSynchronousRequest

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/32643207/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 07:41:20  来源:igfitidea点击:

iOS9 sendSynchronousRequest deprecated

iosswift

提问by Mike Keskinov

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. If your trying to add a try statement, I modified his answer as followed:

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

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

回答by Nilesh Patel

Use NSURLSessioninstead 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,

对于斯威夫特,

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

回答by Mike Keskinov

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 NSURLConnectionto NSURLSessionin the complex solution where it was quite a hassleto just change to async approach. With this solution the migration is just method name replacement.

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

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 NSURLConnectionto this method):

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

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

回答by Nick H247

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]. e.g.

如果您需要阻塞当前线程(如 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);

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

回答by Hunt3rDe

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

回答by PJ_Finnegan

Swift 4 / Xcode 9

斯威夫特 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")
...

回答by Dipen Panchasara

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

回答by Victor Choy

Here is a complete version of mine with dispatch_semaphore_t and return response and error without block assign warning . Thank @Nick H247 and @Mike Keskinov.

这是我的一个完整版本,带有 dispatch_semaphore_t 并返回响应和错误而没有块分配警告。感谢@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;
}