Afmystificerende @escaping, @non-escaping, @autoclosure og curry funktion
lukninger er selvstændige blokke af funktionalitet, der kan sendes rundt og bruges i din kode.
— Apple
lukninger kan fange og gemme henvisninger til eventuelle konstanter og variabler fra den sammenhæng, hvori de er defineret, kendt som Lukning over dermed lukning. Du kan tænke på en lukning som en funktion, der ikke har sit eget navn og fanger værdier fra sit miljø. Funktioner og lukninger er førsteklasses objekter i Hurtig: du kan gemme dem, videregive dem som argumenter til funktioner og behandle dem som enhver anden værdi eller objekt. Passering af lukninger som færdiggørelseshåndterere er et almindeligt mønster i mange API ‘ er. Standard hurtigt bibliotek bruger lukninger hovedsagelig til håndtering af begivenheder og tilbagekald.
funktioner er selvstændige stykker kode, der udfører en bestemt opgave. Du giver en funktion et navn, der identificerer, hvad den gør, og dette navn bruges til at “kalde” funktionen til at udføre sin opgave, når det er nødvendigt. Du definerer en funktion med nøgleordet func
. Funktioner kan tage ingen til mange parametre, variadiske parametre og returnere ingen eller flere parametre.
funktionstyper
Funktionstype består af parametertyperne og funktionens returtype. For ovenstående eksempel er funktionstypen:(Int, Int) -> Int
dette kan læses som: “en funktion, der har to parametre, begge af typen Int
, og som returnerer en værdi af typen Int
.”Funktionstype kan indstilles som parameter eller returtype af funktion.
funktionstyper kan tildeles til enhver variabel som denne:
var mathFunction: (Int, Int) -> Int = add
funktioner er særlige tilfælde af lukninger. Lukninger tager en af tre former:
- globale funktioner: de har et navn og kan ikke fange værdi.
- indlejrede funktioner: de har et navn og kan fange værdier fra deres omsluttende funktion.
- Lukningsudtryk: de har ikke navn og kan fange værdier fra deres omgivende kontekst.
Lukning Udtryk:
Lukning kan oprettes ved at sætte en funktionstype inde i krøllede seler og in
nøgleord efter returtypen.
Shorthand Argument Navne
Lukningsargumenter kan henvise til en position, dvs. ,
,
,
og så videre.
implicitte afkast fra Lukning:
single-udtryk lukninger kan implicit returnere resultatet af deres enkelt udtryk ved at udelade return
søgeord fra deres erklæring.
for en lukning af flere linjer kan return
søgeord ikke udelades.
Efterfølgende Lukning:
hvis du har brug for at overføre et lukningsudtryk til en funktion, da funktionens sidste argument og lukningsudtryk er for langt, kan det skrives som efterfølgende lukning. En efterfølgende lukning skrives efter funktionsopkaldets parenteser (), selvom det stadig er et argument for funktionen. Når du bruger syntaksen for efterfølgende lukning, skriver du ikke argumentetiketten for lukningen som en del af funktionsopkaldet.
hvis Lukning er den sidste parameter til en metode, giver hurtig dig mulighed for at skrive sådan 🖕
brugen af efterfølgende lukningssyntaks indkapsler lukningens funktionalitet umiddelbart efter den funktion, som lukningen understøtter, uden at skulle pakke hele lukningen inden for reduce(_:)
– metodens ydre parenteser.
optagelse af værdier:
en lukning kan fange konstanter og variabler fra den omgivende kontekst, hvori den er defineret. Lukningen kan derefter henvise til og ændre værdierne for disse konstanter og variabler inde fra dens krop, selvom det oprindelige omfang, der definerede konstanterne og variablerne, ikke længere eksisterer.
i Hurtig, den enkleste form for en lukning, der kan fange værdier er en indlejret funktion, skrevet i kroppen af en anden funktion. En indlejret funktion kan fange en hvilken som helst af dens ydre funktions argumenter og kan også fange alle konstanter og variabler defineret inden for den ydre funktion.
denne makeIncrementer
funktion accepterer et argument, dvs.Int som input og returnerer en funktionstype, dvs. () -> Int
. Dette betyder, at det returnerer en funktion snarere end en simpel værdi. Den funktion, den returnerer, har ingen parametre og returnerer en Int
værdi, hver gang den kaldes.
her amount
er argument, runningTotal
er erklæret som variabel og initialiseret med 0. Indlejret funktion incrementer
fanger amount
og runningTotal
fra omgivende kontekst.
lad os se makeIncrementer
i aktion:
Bemærk: Som en optimering kan vi i stedet fange og gemme en kopi af en værdi, hvis denne værdi ikke muteres af en lukning, og hvis værdien ikke muteres, efter at lukningen er oprettet.
hurtig håndterer også al hukommelsesstyring, der er involveret i bortskaffelse af variabler, når de ikke længere er nødvendige.
for at slippe af med Lang Lukning udtryk i funktion argument kan du bruge typealias.
ikke-undslippende lukninger:
Lukningsparametre undslippede som standard før Hurtig 3. En lukning ville ikke undslippe funktionskroppen, hvis lukningsparametre er markeret som ikke-undslippe
i hurtig 3 er det blevet vendt. Når du passerer en lukning som funktionsargumentet, bliver lukningen udført med funktionens krop og returnerer kompilatoren tilbage. Når udførelsen slutter, går den beståede lukning uden for rækkevidde og har ikke mere eksistens i hukommelsen.
det mindste du behøver at vide
Lukningsparametre er ikke-undslippe som standard, hvis du vil undslippe lukningsudførelsen, skal du bruge @escaping med lukningsparametrene.
livscyklus for den ikke-undslippende lukning:
1. Pass lukningen som et funktionsargument under funktionsopkaldet.
2. Gør noget arbejde i funktion og udfør derefter lukningen.
3. Funktion vender tilbage.
på grund af Bedre hukommelsesstyring og optimeringer har hurtig ændret alle lukninger til ikke at undslippe som standard. CaptureList.swift
er et eksempel på ikke-undslippe lukning.
Bemærk: @non-escaping annotation gælder kun for funktionstyper
Escaping lukninger:
en lukning siges at undslippe en funktion, når lukningen overføres som et argument til funktionen, men kaldes efter funktionen vender tilbage. Markering af en lukning med @escaping
betyder, at du skal henvise til self
eksplicit inden for lukningen.
livscyklus for @escaping-lukningen:
1. Pass lukningen som funktionsargument under funktionsopkaldet.
2. Gør noget ekstra arbejde i funktion.
3. Funktion udfør lukningen asynkront eller gemt.
4. Funktion vender tilbage.
lad os se, hvor lukninger som standard undslipper:
- variabler af funktionstype er implicit escaping
- typealiaser er implicit escaping
- valgfri lukninger er implicit escaping
almindelig fejl:
tildeling af ikke-escaping lukning til escaping lukning. Der er 2 måder at løse dette på:
- Marker lukning som escaping
- eller behold standard @noescape-opførsel ved at gøre lukningen valgfri
Autoclosures:
hurtig ‘ s @autoclosure
attribut giver dig mulighed for at definere et argument, der automatisk bliver pakket ind i en lukning. Det kræver ingen argumenter, og når det kaldes, returnerer det værdien af det udtryk, der er pakket ind i det. Denne syntaktiske bekvemmelighed giver dig mulighed for at udelade seler omkring en funktions parameter ved at skrive et normalt udtryk i stedet for en eksplicit lukning.
for eksempel tager funktionen assert(condition:message:file:line:)
en autoklosur for dens condition
og message
parametre; dens condition
parameter evalueres kun i debug builds, og dens message
parameter evalueres kun, hvis condition
er false
.
func assert(_ expression: @autoclosure () -> Bool,
_ message: @autoclosure () -> String) {}
at bruge @autoclosure
med @escaping
attribut syntaks er:
@autoclosure @escaping () -> Bool
lukninger vs blokke:
“hurtige lukninger og Objective-C-blokke er kompatible, så du kan overføre hurtige lukninger til Objective-C-metoder, der forventer blokke. Hurtige lukninger og funktioner har samme type, så du kan endda videregive navnet på en Hurtig funktion. Lukninger har lignende fangstsemantik som blokke, men adskiller sig på en vigtig måde: variabler kan ændres snarere end kopieres. Med andre ord er adfærden af _ _ block i Objective-C standardadfærden for variabler i hurtig.”
lukninger vs delegerede:
løsningen afhænger af problemet. Desuden skifter Apple sit fokus til Tilbagekaldsmønster.
https://medium.com/@abhimuralidharan/functional-swift-all-about-closures-310bc8af31dd
https://medium.com/@kumarpramod017/what-do-mean-escaping-and-nonescaping-closures-in-swift-d404d721f39d
https://oleb.net/blog/2016/10/optional-non-escaping-closures/
https://swiftunboxed.com/lang/closures-escaping-noescape-swift3/
https://medium.com/@johnsundell/using-autoclosure-when-designing-swift-apis-67fe20a8b2e