Jest sporo tu, więc będziemy rozbicie go jeden kawałek na raz:
func fetchOrders(_ completionHandler: (_ orders: [Order]) -> Void)
- Jest to funkcja zwana
fetchOrders
.
- Ma jeden parametr (
completionHandler
) i nic nie zwraca.
- Pierwsza
_
wskazuje, że nie ma "zewnętrznej nazwy" pierwszego parametru. Oznacza to, że nie musisz tego oznaczać (w rzeczywistości nie możesz). (Z subtelnych powodów, które tak naprawdę nie mają znaczenia tutaj, wierzę, że autor popełnił błąd używając _
tam, i nie zrobiłbym tego.)
completionHandler
to "nazwa wewnętrzna", jaki parametr nazywa się wewnątrz funkcja.
- Typ
completionHandler
to (_ orders: [Order]) -> Void
. Złamiemy to teraz.
- Ta wartość jest zamknięta, która pobiera
[Order]
(tablica Order
) i zwraca Void
. Nieformalnie oznacza to "nic nie zwraca", ale dosłownie oznacza, że zwraca pustą krotkę ()
.
- Składnia
_ orders:
jest w praktyce komentarzem. Zasadniczo nazwa _
jest nazwą zewnętrzną (ale jest to jedyna prawnie zewnętrzna nazwa zamknięcia), a orders
jest nazwą wewnętrzną, ale w rzeczywistości parametry zamknięcia nie mają nazw w żaden znaczący sposób, więc jest to czysto informacyjne.
- Uważam, że jest to słabe wykorzystanie systemu komentowania parametrów zamknięcia.Od
orders
mówi nam nic więcej niż [Order]
, bym go pominął i zrobił typ tylko ([Order]) -> Void
.
Teraz przechodzimy do następnego wiersza:
ordersStore.fetchOrders { (orders:() throws -> [Order]) -> Void in
- To wywołuje metodę
fetchOrders
na ordersStore
. Z tego kodu możemy stwierdzić, że fetchOrders
przyjmuje parametr zamknięcia. Jest to tak zwana składnia "końcowe zamknięcie" w Swift i dlatego nie użyłbym _
do naszego zamknięcia. Przy składni zamknięcia końcowego zewnętrzna nazwa parametru nie jest potrzebna.
- Autor podał tutaj informacje o typie, które prawdopodobnie nie były konieczne, ale i tak możemy je zbadać. Prawdopodobnie zostałoby to napisane jako
{ orders in
, ale prawdopodobnie czytelnik byłby zaskoczony tym nieco niecodziennym kodem.
- Przekazano nam zamknięcie o nazwie
orders
, które nie przyjmuje niczego i zwraca [Order]
lub powoduje błąd. Zasadniczo jest to sposób, aby powiedzieć, że fetchOrders
może zawieść.
- Autor pracuje nad niezręcznością w systemie Swift
throws
, który nie ma naturalnego sposobu wyrażania asynchronicznej akcji, która może zawieść. Jest to jeden sposób, aby to naprawić; przekazujesz funkcję rzucania (to znaczy możliwą awarię). Nie faworyzuję tego podejścia, preferuję użycie enum Result
dla tej sprawy, ponieważ myślę, że skaluje się lepiej i unika możliwych niezamierzonych efektów ubocznych, ale to jest dyskusyjny punkt (a społeczność Swift tak naprawdę nie zdecydowała, jak sobie z tym poradzić powszechny problem).
To wszystko prowadzi nas do:
do {
let orders = try orders()
completionHandler(orders)
} catch {
completionHandler([])
}
- To gdzie zamknięcie
orders
jest oceniany. (Jest to bardzo ważne, jeśli wystąpią efekty uboczne, jeśli wystąpią one, które mogą znajdować się w innej kolejce, niż zamierzano, to jeden z powodów, dla których nie faworyzuję tego wzorca). Jeśli zamknięcie się powiedzie, zwrócimy wynik , w przeciwnym razie zwracamy []
poniżej w catch
.
- W tym szczególności przypadku podejście
throws
jest nieco głupie, bo jest cicho spłaszczone do []
nawet bez wiadomości dziennika. Jeśli nie przejmujemy się tymi błędami, powinna ona powrócić dopiero po []
i nie być pomylona z throws
. Ale możliwe jest, że inni rozmówcy sprawdzają błędy.
- W każdym przypadku nazywamy zamknięcie
completionHandler
naszym wynikiem, łącząc je z powrotem z naszym oryginalnym rozmówcą.
to zrobić blok/catch mogło być prościej zapisać jako:
let completedOrders = try? orders() ?? []
completionHandler(completedOrders)
To czyni go bardziej zrozumiałym, że jesteśmy ignorując błędy, obracając ją w opcjonalny i pozwala uniknąć powielania kodu podczas rozmowy do completionHandler
.
(ja po prostu dodać dodatkowy let
wiązania, aby kod trochę łatwiejsze do odczytania;. Nie jest to konieczne)
Czytając rozdział „Funkcje” W książce Swift odniesienia może być pomocne ... –