Pytanie Jakie wsparcie dla poziomu języka (jeśli istnieje) ma Swift dla programowania asynchronicznego?


Programowanie asynchroniczne jest koniecznością w przypadku responsywnych interfejsów użytkownika, gdy aplikacja musi komunikować się w nieprzewidywalnych sieciach (np. Aplikacje inteligentnego telefonu). Interfejs użytkownika musi pozostać responsywny, czekając, aż wyniki powrócą z serwerów gdzieś przez Internet.

W większości języków programista aplikacji musi zaimplementować własne maszyny stanowe (być może przy użyciu zamknięć), aby reagować na asynchroniczne wywołania zwrotne i / lub koordynować mnożenie wątków za pomocą blokad.

Oba te są bardzo podatne na błędy, a nie dla fait hearted!

(c # wprowadził asynchroniczne słowo kluczowe, aby pomóc w tym, tylko czas (co najmniej 5 lat) wskaże, czy jest to dobre rozwiązanie.)

Czy Swift ma wbudowaną obsługę wspomagającą pisanie asynchronicznego kodu?


18
2018-06-03 09:02


pochodzenie


możliwy duplikat W jaki sposób nowy język programowania Swift firmy Apple obsługuje bloki i żądania asynchroniczne? - weston


Odpowiedzi:


Chociaż nie jest to wbudowana funkcja językowa, może to być interesujące możliwe jest zaimplementowanie stylu C # async/await dla Swift, a to ze względu na specjalną składnię dostępną dla ostatniego argumentu zamknięcia wywołania funkcji, wygląda nawet na to, że może być częścią tego języka.

Jeśli ktokolwiek jest zainteresowany, możesz uzyskać kod do tego na Bitbucket. Oto krótki przegląd tego, co jest możliwe:

let task = async { () -> () in
  let fetch = async { (t: Task<NSData>) -> NSData in
    let req = NSURLRequest(URL: NSURL.URLWithString("http://www.google.com"))
    let queue = NSOperationQueue.mainQueue()
    var data = NSData!
    NSURLConnection.sendAsynchronousRequest(req,
                                            queue:queue,
      completionHandler:{ (r: NSURLResponse!, d: NSData!, error: NSError!) -> Void in
        data = d
        Async.wake(t)
      })
    Async.suspend()
    return data!
  }

  let data = await(fetch)
  let str = NSString(bytes: data.bytes, length: data.length,
                     encoding: NSUTF8StringEncoding)

  println(str)
}

Ponadto, jeśli chcesz czegoś takiego jak zsynchronizowane, spróbuj tego:

func synchronized(obj: AnyObject, blk:() -> ()) {
  objc_sync_enter(obj)
  blk()
  objc_sync_exit(obj)
}

var str = "A string we can synchronise on"

synchronized(str) {
  println("The string is locked here")
}

13
2018-06-13 09:23



To jest miłe, chociaż powinno być standardowe, aby kod był bardziej czytelny. - Blaze
Czy to jest bezpieczne? Używanie setjmp / longjmp w konfliktach Objective-C z pulami autorelease (które są implementowane jako stos cieni w środowisku wykonawczym, ale nie są publicznymi ABI) - o ile mi wiadomo, Swift używa również autorelease. - pmdj
w drugim przykładzie, co jeśli blk zgłasza wyjątek? - gregswiss
@gregswiss Kiedy początkowo to pisałem, Swift nie miał wyjątków. Wciąż nie ma takich wyjątków, o których myślisz. Jeśli, z drugiej strony, dany blok rzuca wyjątki Celu C, masz kłopoty; ale to prawda ogólnie dla kodu Swift. - alastair
@pmdj To dobry punkt; prawdopodobnie nie jest autorelease bezpieczny, jak to jest. Powinno być możliwe naprawienie go przez majsterkowanie za pomocą klucza pthread, którego używa system autorelease, choć jest to oczywiście ogromny hack. Nie jestem pewien, czy Swift używa autorelease, FWIW. - alastair


Podejście Swifta do programowania asynchronicznego jest takie samo jak w Celu C: użyj Grand Central Dispatch. Możesz przekazywać zamknięcia do funkcji gcd dispatch_, tak jak w ObjC. Jednak ze względów estetycznych możesz także przekazać swoje zamknięcie (blok) po zamkniętym nawiasie:

dispatch_async(dispatch_get_main_queue()) {
    println("async hello world")
}

11
2018-06-03 09:44



Cel C ma słowo kluczowe @synchronizacja, więc nie wydaje się to być prawdą. - Blaze
@Blaze Masz na myśli @synchronized? To naprawdę syntaktyczny cukier do dzwonienia objc_sync_enter()/objc_sync_exit(). Możesz to zrobić w Swift, jeśli chcesz, możesz nawet dodać podobną składnię, jeśli chcesz. - alastair
ah, po prostu przeczytaj komentarz poniżej. miły. - Blaze
@synchronized jest mechanizmem, który wyprzedził GCD i ogólnie uważa się, że nie jest tak dobry jak przy użyciu GCD. Warto zauważyć, że używa on blokady rekursywnej, która jest o wiele droższą operacją synchronizacji niż przy użyciu kolejki wysyłkowej - Kevin Ballard