Demystifying @ escaping, @ non-escaping, @autoclosure og curry funksjon
Nedleggelser er selvstendige blokker av funksjonalitet som kan sendes rundt og brukes i koden.
— Apple
Nedleggelser kan fange opp og lagre referanser til eventuelle konstanter og variabler fra konteksten der de er definert, kjent som lukking over dermed Lukking. Du kan tenke på en lukning som en funksjon som ikke har et eget navn og fanger noen verdier fra sitt miljø. Funksjoner og nedleggelser er førsteklasses objekter I Swift: du kan lagre dem, sende dem som argumenter til funksjoner, og behandle dem som du ville enhver annen verdi eller objekt. Passerer nedleggelser som ferdigstillelse handlers er et vanlig mønster i mange Apier. Standard Swift library bruker nedleggelser mest for hendelseshåndtering og tilbakeringinger.
Funksjoner er selvstendige kodebiter som utfører en bestemt oppgave. Du gir en funksjon et navn som identifiserer hva den gjør, og dette navnet brukes til å «ringe» funksjonen for å utføre oppgaven når det trengs. Du definerer en funksjon med nøkkelordet func
. Funksjoner kan ta ingen til mange parametere, variadiske parametere og returnere ingen eller flere parametere.
Funksjonstyper
Funksjonstypen består av parametertypene og returtypen for funksjonen. For eksempel er funksjonstypen:(Int, Int) -> Int
Dette kan leses som: «en funksjon som har to parametere, begge av typen Int
og som returnerer en verdi av typen Int
.»Funksjonstype kan settes som parameter eller retur type funksjon.
Funksjonstyper kan tilordnes en variabel som dette:
var mathFunction: (Int, Int) -> Int = add
Funksjoner er spesielle tilfeller av nedleggelser. Nedleggelser ta en av tre former:
- Globale funksjoner: De har et navn og kan ikke fange verdi.
- Nestede funksjoner: De har et navn og kan fange verdier fra sin omsluttende funksjon.
- Lukkeuttrykk: De har ikke navn og kan fange verdier fra sin omkringliggende kontekst.
Lukkeuttrykk:
Lukking kan opprettes ved å sette en funksjonstype inne i krølltenger og in
søkeord etter returtypen.
Shorthand Argumentnavn
Avslutningsargumenter kan referere til en posisjon, dvs. ,
,
,
og så videre.
Implisitt Avkastning fra Nedleggelse:
enkeltuttrykkslukninger kan implisitt returnere resultatet av deres enkeltuttrykk ved å utelate return
søkeordet fra erklæringen.
return
søkeord kan ikke utelates for å lukke et uttrykk med flere linjer.
Etterfølgende Lukking:
hvis du må sende et lukkeuttrykk til en funksjon som funksjonens siste argument og lukkeuttrykk er for langt, kan det skrives som etterfølgende lukking. En etterfølgende lukning skrives etter funksjonskallets parenteser (), selv om det fortsatt er et argument for funksjonen. Når du bruker syntaksen for etterfølgende lukking, skriver du ikke argumentetiketten for lukking som en del av funksjonskallet.
hvis lukning er den siste parameteren til en metode, lar swift deg skrive slik 🖕
bruken av etterfølgende lukking syntaks innkapsler pent lukkings funksjonalitet umiddelbart etter funksjonen som nedleggelse støtter, uten å måtte vikle hele lukkingen i reduce(_:)
metodens ytre parenteser.
Fange Verdier:
en lukking kan fange konstanter og variabler fra den omkringliggende konteksten der den er definert. Lukkingen kan da referere til og endre verdiene til disse konstantene og variablene fra kroppen, selv om det opprinnelige omfanget som definerte konstantene og variablene ikke lenger eksisterer.
I Swift er Den enkleste formen for en lukning som kan fange verdier en nestet funksjon, skrevet i kroppen til en annen funksjon. En nestet funksjon kan fange noen av dens ytre funksjonens argumenter og kan også fange noen konstanter og variabler definert i den ytre funksjonen.
denne makeIncrementer
– funksjonen godtar ett argument dvs. Int som input og returnerer en funksjonstype dvs. () -> Int
. Dette betyr at den returnerer en funksjon, i stedet for en enkel verdi. Funksjonen den returnerer har ingen parametere, og returnerer en Int
verdi hver gang den kalles.
her amount
er argument, runningTotal
deklareres som variabel og initialiseres med 0. Nestet funksjon incrementer
fanger amount
og runningTotal
fra omkringliggende kontekst.
La oss se makeIncrementer
i aksjon:
Merk: Som en optimalisering kan Swift i stedet fange og lagre en kopi av en verdi hvis den verdien ikke er mutert av en lukking, og hvis verdien ikke er mutert etter at lukkingen er opprettet.
Swift håndterer også all minnehåndtering involvert i avhending av variabler når de ikke lenger er nødvendig.
for å kvitte seg med lang lukning i funksjonsargument kan du bruke typealias.
Ikke-escaping Lukninger:
Lukkeparametere ble rømt som standard før Swift 3. En lukking ville ikke unnslippe funksjonskroppen hvis lukkeparametere er merket som ikke-escaping
I Swift 3 er det blitt reversert. Når du passerer en lukning som funksjonsargumentet, blir lukkingen utført med funksjonens kropp og returnerer kompilatoren tilbake. Når utførelsen slutter, går den passerte lukkingen ut av omfang og har ikke mer eksistens i minnet.
Det Minste Du Trenger Å Vite
Lukkeparametere er ikke-escaping som standard, hvis du vil unnslippe lukkingen, må du bruke @escaping med lukkeparametrene.
Livssyklus for den ikke-escaping lukning:
1. Pass lukkingen som et funksjonsargument, under funksjonsanropet.
2. Gjør noe arbeid i funksjon og utfør deretter lukkingen.
3. Funksjonen returnerer.
På grunn av bedre minnehåndtering og optimaliseringer har Swift endret alle lukninger for å være ikke-rømmer som standard. CaptureList.swift
er et eksempel på ikke-escaping lukning.
Merk: @non-escaping merknad gjelder bare for funksjonstyper
Rømmer Nedleggelser:
en lukning sies å unnslippe en funksjon når lukkingen sendes som et argument til funksjonen, men kalles etter at funksjonen returnerer. Merking av en lukning med @escaping
betyr at du må referere til self
eksplisitt i lukkingen.
Livssyklus for @ escaping-lukkingen:
1. Pass lukkingen som funksjonsargument, under funksjonsanropet.
2. Gjør litt ekstra arbeid i funksjon.
3. Funksjon utfør lukkingen asynkront eller lagret.
4. Funksjonen returnerer.
La oss se hvor nedleggelser er som standard rømmer:
- Variabler av funksjonstype er implisitt escaping
- typealiaser er implisitt escaping
- Valgfrie lukninger er implisitt escaping
Vanlig Feil:
Tilordne ikke-escaping lukning til escaping lukning. Det er 2 måter å fikse dette på:
- Merk lukking som escaping
- Eller behold standard @noescape-virkemåten ved å gjøre lukkingen valgfri
Autoklosurer:
Swifts @autoclosure
– attributt lar deg definere et argument som automatisk blir pakket inn i en lukning. Det tar ikke noen argumenter, og når det kalles, returnerer det verdien av uttrykket som er pakket inn i det. Denne syntaktiske bekvemmeligheten lar deg utelate braces rundt en funksjons parameter ved å skrive et normalt uttrykk i stedet for en eksplisitt lukning.
for eksempel tar funksjonen assert(condition:message:file:line:)
en autoklosning for parametrene condition
og message
; parameteren condition
evalueres bare i feilsøkingsbygg, og parameteren message
evalueres bare hvis condition
er false
.
func assert(_ expression: @autoclosure () -> Bool,
_ message: @autoclosure () -> String) {}
for å bruke @autoclosure
med @escaping
attributt syntaks er:
@autoclosure @escaping () -> Bool
Nedleggelser vs Blokker:
«Hurtige nedleggelser og Objective-C-blokker er kompatible, slik at Du kan sende Hurtige nedleggelser til Objective-C-metoder som forventer blokker. Swift nedleggelser og funksjoner har samme type, slik at du selv kan passere navnet På En Swift-funksjon. Nedleggelser har lignende fangstsemantikk som blokker, men varierer på en viktig måte: Variabler er foranderlige i stedet for kopiert. Med andre ord er oppførselen til _ _ block i Objective-C standardadferden for variabler i Swift.»
Nedleggelser vs Delegater:
løsningen avhenger av problemet. Videre skifter Apple fokus til Tilbakeringingsmønster. UIAlertAction
er et eksempel på dette.
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