iOS9 sendSynchronousRequest deprecated

后端 未结 7 1377
自闭症患者
自闭症患者 2020-12-24 13:15

Warning:\'sendSynchronousRequest(_:returningResponse:)\' was deprecated in iOS 9.0: Use [NSURLSession dataTaskWithRequest:completionHandler:] (see NSURLSe

相关标签:
7条回答
  • 2020-12-24 13:39

    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:

    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:

    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")
    ...
    
    0 讨论(0)
  • 2020-12-24 13:44

    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. 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):

    //NSData *data = [NSURLConnection sendSynchronousRequest:theRequest returningResponse:&resp error:&err];
    NSData *data = [self sendSynchronousRequest:theRequest returningResponse:&resp error:&err];
    
    0 讨论(0)
  • Use NSURLSession instead like below,

    For 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()
    
    0 讨论(0)
  • 2020-12-24 13:52

    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.

    - (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;
    }
    
    0 讨论(0)
  • 2020-12-24 14:02

    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.

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

    let semaphore = DispatchSemaphore(value:0)
    
    URLSession.shared.dataTask(with: serverUrl) { (httpData, response, error) in
        // handle response
        semaphore.signal()
    }.resume()
    
    semaphore.wait()
    
    0 讨论(0)
  • 2020-12-24 14:05

    I have modified the code of Nilesh Patel a little bit, so you can use the old call, just by changing class name.

    + (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;
        }
    }
    
    0 讨论(0)
提交回复
热议问题