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#>)
Ответы
Ответ 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;
}