Es gibt ziemlich viel hier, so dass wir es brechen ein Stück zu einer Zeit:
func fetchOrders(_ completionHandler: (_ orders: [Order]) -> Void)
- Dies ist eine Funktion
fetchOrders
genannt.
- Es hat einen Parameter (
completionHandler
) und gibt nichts zurück.
- Die erste
_
zeigt an, dass es keinen "externen Namen" des ersten Parameters gibt. Das heißt, Sie müssen es nicht beschriften (in der Tat können Sie nicht). (Aus subtilen Gründen, die hier nicht wirklich wichtig sind, glaube ich, dass der Autor einen Fehler gemacht hat, _
dort, und das hätte ich nicht getan.)
- Der
completionHandler
ist der "interne Name", wie der Parameter im Inneren heißt die Funktion.
- Der Typ
completionHandler
ist (_ orders: [Order]) -> Void
. Wir werden das jetzt durchbrechen.
- Dieser Wert ist ein Verschluss, der eine
[Order]
(array of Order
) und gibt Void
nimmt. Informell bedeutet dies "gibt nichts zurück", bedeutet aber wörtlich, dass es das leere Tupel ()
zurückgibt.
- Die
_ orders:
Syntax ist in der Praxis ein Kommentar. Im Prinzip ist der _
ein externer Name (aber das ist der einzige zulässige externe Name für eine Schließung), und orders
ist ein interner Name, aber in Wirklichkeit haben Closures-Parameter keine Namen in irgendeiner sinnvollen Weise, so dass dies rein informativ ist.
- Ich glaube, dies ist eine schlechte Verwendung des Kommentarsystems Schließung Parameter.Seit
orders
erzählt uns nichts mehr als [Order]
, hätte ich es weggelassen, und machte den Typ nur ([Order]) -> Void
.
Jetzt werden wir in der nächsten Zeile drehen:
ordersStore.fetchOrders { (orders:() throws -> [Order]) -> Void in
- Dies ruft die
fetchOrders
Methode auf ordersStore
. Wir können anhand dieses Codes erkennen, dass fetchOrders
einen Verschlussparameter annimmt. Dies wird in Swift als "Trailing Closure" -Syntax bezeichnet, weshalb ich die _
für unsere Schließung nicht verwendet hätte. Bei einer abschließenden Closure-Syntax wird der externe Name des Parameters nicht benötigt.
- Der Autor hat hier Typinformationen angegeben, die wahrscheinlich nicht notwendig waren, aber wir können es trotzdem erkunden. Dies hätte wahrscheinlich nur als
{ orders in
geschrieben werden können, aber dann wäre der Leser wahrscheinlich von diesem etwas ungewöhnlichen Code überrascht gewesen.
- Wir wurden eine Schließung namens
orders
übergeben, die nichts nimmt und [Order]
zurückgibt oder einen Fehler auslöst. Grundsätzlich ist dies eine Möglichkeit zu sagen, dass fetchOrders
möglicherweise fehlschlagen.
- Der Autor arbeitet um eine Peinlichkeit in Swifts
throws
System, das keine natürliche Möglichkeit hat, eine asynchrone Aktion auszudrücken, die fehlschlagen könnte. Dies ist eine Möglichkeit, es zu beheben; Sie übergeben eine werfen (d. h. eine möglicherweise scheitern) Funktion. Ich bevorzuge diesen Ansatz nicht, ich bevorzuge eine Result
enum für diesen Fall, weil ich denke, dass es besser skaliert und mögliche unbeabsichtigte Nebenwirkungen vermeidet, aber das ist ein strittiger Punkt (und die Swift-Community hat nicht wirklich entschieden, wie sie damit umgehen soll häufiges Problem).
Das alles führt uns zu:
do {
let orders = try orders()
completionHandler(orders)
} catch {
completionHandler([])
}
- Hier wird der
orders
Schließung ausgewertet wird. (Dies ist sehr wichtig; wenn orders
Nebenwirkungen hat, tritt dies auf, wenn sie auftreten, die sich möglicherweise in einer anderen Warteschlange als beabsichtigt befinden. Das ist ein Grund, warum ich dieses Muster nicht favorisiere.) Wenn der Abschluss erfolgreich ist, geben wir sein Ergebnis zurück sonst geben wir []
in der catch
unten zurück.
- In diesem insbesondere Fall der
throws
Ansatz ist etwas albern, weil es still in []
abgeflacht ist, ohne auch nur eine Log-Nachricht. Wenn wir uns nicht um die Fehler kümmern, dann sollte der Fehler []
mit throws
und throws
zurückgegeben werden. Es ist jedoch möglich, dass andere Anrufer die Fehler überprüfen.
- In beiden Fällen nennen wir die
completionHandler
Schließung mit unserem Ergebnis, verketten diese zurück zu unserem ursprünglichen Anrufer.
Dieser do/catch-Block mehr haben könnte einfach geschrieben als:
let completedOrders = try? orders() ?? []
completionHandler(completedOrders)
Dies macht deutlicher, dass wir Fehler sind zu ignorieren, indem sie es in eine optionale Dreh und vermeidet Code-Duplizierung des Anrufs zu completionHandler
.
(Ich füge nur die zusätzlichen let
den Code ein wenig leichter lesbar machen verbindlich;. Es ist nicht erforderlich)
Lesen Sie im Kapitel „Funktionen“ in dem Buch Swift Referenz könnte hilfreich sein ... –