2015-05-08 10 views
7

Jestem względnie nowym użytkownikiem Swift i Xcode w ogóle i znajduję wiele trudności, próbując to rozgryźć.Uruchom kod tylko po zakończeniu funkcji asynchronicznej

Zajmuję się tworzeniem aplikacji korzystającej z serwera zaplecza Parse.com. Aby nie blokować głównego wątku, zawsze, gdy aplikacja pobiera coś z serwera, odbywa się on asynchronicznie na innym wątku. Jednak reszta kodu nadal jest wykonywana w głównym wątku i ulega awarii, gdy dane, które powinny mieć z serwera, nie zostały jeszcze pobrane. Chciałbym wiedzieć, jak wywoływać funkcje uruchamiane po zakończeniu funkcji asynchronicznej, a to musi być zrobione dla funkcji w osobnych plikach.

Czytałem, że zamknięcia mogą pomóc w tym, ale znalazłem tam składnię bardzo trudne i wyjaśnienie byłoby bardzo mile widziane. Ale jakikolwiek sposób byłby bardzo pomocny.

Dzięki

Odpowiedz

13

Cóż, wystarczy wywołać funkcję na koniec asynchronicznego wywołania zwrotnego. To jest, gdy asynchroniczne wywołanie zwrotne zostało zakończone - jest wtedy, gdy wszystko inne w asynchronicznym wywołaniu zwrotnym zostało zakończone! Tak więc, na przykład:

func myMethod() { 
    // ... code ... 
    somebody.doSomethingWith(someObject, asynchronousCallback: { 
     (thing, otherThing) in 
     // ... do whatever 
     // --> CALL THE FUNCTION! 
    }) 
    // ... code ... 
} 

Jeśli problem jest to, że nie wiedzieć co funkcja zadzwonić, można skonfigurować otaczającego funkcję/obiekt tak, że ktoś może ręka ty funkcja, która jest następnie co zadzwonić w miejsce, gdzie powiedziałem "zadzwoń do funkcji" w powyższym.

Na przykład:

func myMethod(f:() ->()) { // we receive the function as parameter 
    // ... code ... 
    somebody.doSomethingWith(someObject, asynchronousCallback: { 
     (thing, otherThing) in 
     // ... do whatever 
     // --> CALL THE FUNCTION, by saying: 
     f() 
    }) 
    // ... code ... 
} 
+0

można wyjaśnić w jaki sposób przekazać funkcję? Zrozumiałem wcześniej, że uruchamiasz funkcję, w której napisałeś "zadzwoń do funkcji", ale funkcja, jak powiedziałem, znajduje się w innym pliku. Konkretny przypadek, nad którym teraz pracuję polega na tym, że napisałem funkcję, która najpierw sprawdza, czy poszukiwany obiekt znajduje się w lokalnym magazynie danych, a jeśli nie, sprawdza serwer. Ponieważ chcę, żeby to działało wszędzie, umieściłem to w osobnym pliku. Ale nadal potrzebuję go do wywoływania funkcji w klasie, która go nazwała. Dzięki jeszcze raz. – Acoop

+0

Mogę z pewnością to wyjaśnić _linguistically_. W Swift funkcje są pierwszymi obywatelami, więc funkcja A może przekazać funkcję B do funkcji C, która może zapamiętać funkcję B. Następnie funkcja C lub inna funkcja z dostępem do zapisanej funkcji B może _ wywołać_ funkcję B. W ten sposób wszystkie wywołania zwrotne działają. Kiedy mówisz 'UIView.animateWithDuration() {...}', przekazujesz to Cocoa - funkcję, którą wywoła w celu wykonania animacji. Zobacz także moją książkę: http://www.apeth.com/swiftBook/ch02.html#_function_as_value – matt

+0

Jednak sposób, w jaki to zrobisz _architecturally_, należy do Ciebie. W powyższym przykładzie 'myMethod' może przyjąć funkcję jako parametr; następnie w "zadzwoń do funkcji", nazywasz to. Ale istnieje wiele innych możliwych scenariuszy. Zobacz przykładowy kod na przykład: https://github.com/mattneub/Programming-iOS-Book-Examples/blob/master/bk2ch24p842downloader/ch37p1099downloader/MyDownloader.swift – matt

3

Rozwijając na odpowiedź Matta, można dokonać myMethod metoda, która trwa zamknięcie jako parametr:

​func​ ​myMethod​(​completionBlock​: (result: String) ->()) 
{ 
    // ... code ... 
    somebody.doSomethingWith(someObject, asynchronousCallback: { 
     (thing, otherThing) in 
     // ... do whatever 
     completionBlock(thing) 
    }) 
    // ... code ... 
}