2015-09-18 19 views
21

Uwaga: 'sendSynchronousRequest (_: returningResponse :)' została zaniechana w iOS 9.0: Stosowanie [NSURLSession dataTaskWithRequest: completionHandler:] (patrz NSURLSession)iOS9 sendSynchronousRequest przestarzałe

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

każdy pomysł jak pozbyć się tego ostrzeżenia? Właśnie zaktualizowałem Swift 1.2 do Swift 2

AKTUALIZACJA: Fonix jest oznaczony jako moja najlepsza odpowiedź. Jeśli próbujesz dodać oświadczenie próbować, ja zmodyfikowano jego odpowiedź jak następuje:

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

Odpowiedz

35

Zastosowanie NSURLSession zamiast jak poniżej,

Dla Objective-C

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

    }] resume]; 

Dla 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() 
+24

Ale czy semantyka jest taka sama? W szczególności 'sendSynchronousRequest' zablokuje wywołujący wątek do czasu otrzymania odpowiedzi, co czasami jest dokładnie tym, czego potrzebujesz. Zgodnie z dokumentami referencyjnymi 'wznawiać' spowoduje wykonanie żądania asynchronicznie, co oznacza, że ​​nie jest dokładnym zamiennikiem przestarzałej funkcji. – aroth

+0

Nie ma argumentu 'queue'. –

+0

To nie jest poprawna odpowiedź, ponieważ nie jest synchroniczna. – codehearted

2

można pozbyć się ostrzeżenia za pomocą sugerowanej metody [NSURLSession dataTaskWithRequest:completionHandler:], NSURLSession jest to, co powinno być w użyciu i teraz nie NSURLConnection

np

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

wiem ostrzeżenie mówi używać NSURLSession ale nie robi mieć metodę sendSynchronousRequest. Jak mogę użyć mojego kodu powyżej z NSURLSession? –

+0

'sendSynchronousRequest' jest metodą z' NSURLConnection', którą musisz zmienić na 'dataTaskWithRequest'. nie jest to metoda klasy, więc musiałbyś wykonać obiekt 'NSURLSession' o nazwie – Fonix

+0

heh, ale z drugiej strony, jeśli jego zbyt wiele kłopotów z przełączeniem na' NSURLSession', to jest tylko ostrzeżenie, możesz nadal używać starej metody, jeśli naprawdę potrzebuję tego w ten sposób – Fonix

2

można ukryć tego ostrzeżenia w projekcie przy użyciu następującego kodu napisać metoda między dyrektywami wejściowych i swojej ostrzeżenia odchodzi.

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

to jest bardzo dobrze wiedzieć, dziękuję! Lubię jednak aktualizować moje klasy, na wypadek gdyby przyszłe aktualizacje usunęły funkcjonalność wycofanych klas. –

+1

@DevTonio przestarzałe klasy nie będą natychmiastowo niedostępne, zajmuje to dużo czasu. Chociaż jest dobry do uaktualnienia kodu. Dzięki za uznanie. –

+3

Jest to ważna część utrzymywania aktualności kodu i przeprowadzania sesji refaktoryzacji w projektach. Nigdy bym tego nie zaakceptował dla projektu z szansą, że nagle pewnego dnia wszyscy moi użytkownicy skontaktowali się ze mną, że tysiące aplikacji zaczęło się zawieszać. Każde powiadomienie powinno być traktowane tak samo jak błąd i być traktowane teraz, nie później. –

22

napisałem następujące rozwiązanie dla przypadków, kiedy rzeczywiście potrzebują dla żądania synchronicznego blokującego bieżące wykonywanie wątku. Używam tego kodu do migracji z NSURLConnection do NSURLSession w kompleksowym rozwiązaniu, gdzie było dość kłopotów po prostu zmienić podejście asynchroniczne. Dzięki temu rozwiązaniu migracja jest po prostu zastąpieniem nazwy metody.

UWAGA: Jeśli masz prosty przypadek, użyj zamiast tego zaakceptowanej odpowiedzi.

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

    *response = resp; 
    *error = err; 
    return data; 
} 

Usage (proste zastąpienie NSURLConnection do tej metody):

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

Jeśli chcesz zablokować bieżącego wątku (jak odpowiedź Mike'a Keskinov za), najlepiej używać GDC semafora zamiast robi [ NSThread sleepForTimeInterval: 0]. na przykład

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

Swift 4/Xcode 9

Jeśli naprawdę chcesz prośba być synchroniczna jak w nieaktualnych semantyki, możesz zablokować główny wątek z pustej pętli na warunek określony prawda przez Wózek oddania:

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: lub jeśli wolisz używać semaforów jak odpowiedź 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") 
... 
0

Trochę zmodyfikowałem kod Nilesh Patel, więc możesz użyć starego połączenia, po prostu zmieniając nazwę klasy.

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

}