Подтвердить что ты не робот

IOS9 sendSynchronousRequest устарел

Предупреждение: 'sendSynchronousRequest (_: returnResponse:)' устарел в iOS 9.0: Используйте [NSURLSession dataTaskWithRequest: completeHandler:] (см. NSURLSession)

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

Любая идея о том, как избавиться от этого предупреждения? Я просто обновился от Swift 1.2 до Swift 2

UPDATE: Fonix отмечен как лучший ответ. Если вы пытаетесь добавить оператор try, я изменил его ответ следующим образом:

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

Ответ 1

Используйте NSURLSession вместо этого, как показано ниже,

Для Objective-C

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

  }] resume];

Для 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()

Ответ 2

Я написал следующее решение для случаев, когда вам действительно нужен синхронный запрос, который блокирует выполнение текущего потока. Я использую этот код для перехода от 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;
}

Использование (просто замените NSURLConnection на этот метод):

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

Ответ 3

Если вам нужно заблокировать текущий поток (например, ответ Майка Кескинова), лучше использовать семафор 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);

Ответ 4

Я немного изменил код 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;
    }
}

Ответ 5

Swift 4/Xcode 9

Если вы действительно хотите, чтобы запрос был синхронным, как в устаревшей семантике, вы можете заблокировать основной поток пустым циклом при условии, установленном 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:, или если вы предпочитаете использовать семафоры, как в ответе 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")
...

Ответ 6

Можно избавиться от предупреждения с помощью предлагаемого метода [NSURLSession dataTaskWithRequest:completionHandler:], NSURLSession - это то, что вы должны использовать сейчас, а не NSURLConnection

например,

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

Ответ 7

вы можете скрыть это предупреждение в своем проекте, используя следующий код: напишите свой метод между директивами ввода, и ваше предупреждение исчезнет.

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

Ответ 8

Вот моя полная версия с 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;
}