aureool te ontdoen @ontsnappen, @niet ontsnappen, @autoclosure en curry functie
Sluitingen zijn zelfstandige blokken van functionaliteit die kan worden doorgegeven rond en gebruikt in je code.
— Apple
Closures kunnen verwijzingen naar constanten en variabelen uit de context waarin ze zijn gedefinieerd vastleggen en opslaan, bekend als closing over vandaar Closure. Je kunt een sluiting zien als een functie die geen eigen naam heeft en alle waarden uit zijn omgeving vangt. Functies en sluitingen zijn eersteklas objecten in Swift: je kunt ze opslaan, als argumenten doorgeven aan functies en ze behandelen zoals je elke andere waarde of object zou doen. Het passeren van sluitingen als voltooiing handlers is een gemeenschappelijk patroon in veel API ‘ s. Standaard Swift bibliotheek gebruikt sluitingen meestal voor event handling en callbacks.
functies zijn zelfstandige stukjes code die een specifieke taak uitvoeren. Je geeft een functie een naam die identificeert wat het doet, en deze naam wordt gebruikt om de functie te “aanroepen” om zijn taak uit te voeren wanneer dat nodig is. U definieert een functie met het func
sleutelwoord. Functies kunnen GEEN nemen aan vele parameters, variadische parameters en retourneren geen of meerdere parameters.
Functietypes
functietype bestaat uit de parametertypes en het returntype van de functie. Voor bovenstaand voorbeeld, functietype is:(Int, Int) -> Int
dit kan gelezen worden als: “een functie die twee parameters heeft, beide van type Int
en die een waarde van type Int
retourneert.”Functietype kan worden ingesteld als parameter of return type functie.
Functietypes kunnen worden toegewezen aan elke variabele zoals deze:
var mathFunction: (Int, Int) -> Int = add
functies zijn een speciaal geval van sluitingen. Sluitingen hebben een van de drie vormen:
- globale functies: ze hebben een naam en kunnen geen waarde vastleggen.
- geneste functies: ze hebben een naam en kunnen waarden vastleggen uit hun omsluitingsfunctie.
- Afsluitingsuitdrukkingen: ze hebben geen naam en kunnen waarden uit hun omringende context vastleggen.
Afsluitingsexpressie:
afsluiting kan worden gemaakt door een functietype in accolades en in
sleutelwoord na het return type te plaatsen.
Steno-Argumentnamen
Afsluitargumenten kunnen verwijzen naar een positie, d.w.z. ,
,
,
en zo verder.
impliciete Returns van afsluiting:
single-expression closures kunnen impliciet het resultaat van hun enkele expressie retourneren door het return
trefwoord uit hun declaratie weg te laten.
voor het afsluiten van een meervoudige expressie kan return
sleutelwoord niet worden weggelaten.
Afsluiting Aan Het Einde:
Als u een afsluitexpressie aan een functie moet doorgeven omdat het laatste argument van de functie te lang is en de afsluitexpressie te lang is, kan deze worden geschreven als afsluiting aan het einde. Een afsluiting aan het einde wordt geschreven na de haakjes van de functie aanroep (), ook al is het nog steeds een argument voor de functie. Wanneer u de syntaxis van de afsluiting aan het einde gebruikt, schrijft u niet het argument label voor de sluiting als onderdeel van de functie aanroep.
Als afsluiting is de laatste parameter aan een methode, dan swift kun je schrijven als dit 🖕
Het gebruik van de trailing sluiting syntaxis netjes kapselt de sluiting van de functionaliteit direct na de functie die sluiting ondersteunt, zonder te wikkel de volledige afsluiting binnen de reduce(_:)
methode buitenste haakjes.
waarden vastleggen:
een afsluiting kan constanten en variabelen vastleggen uit de omringende context waarin het is gedefinieerd. De afsluiting kan dan verwijzen naar en de waarden van die constanten en variabelen wijzigen vanuit zijn lichaam, zelfs als de oorspronkelijke scope die de constanten en variabelen definieerde niet langer bestaat.
in Swift is de eenvoudigste vorm van een afsluiting die waarden kan vastleggen een geneste functie, geschreven in het lichaam van een andere functie. Een geneste functie kan elk van de argumenten van zijn buitenfunctie vastleggen en kan ook alle constanten en variabelen vastleggen die binnen de buitenfunctie zijn gedefinieerd.
deze functie makeIncrementer
accepteert één argument, d.w.z. int, als invoer en geeft een functietype terug, d.w.z. () -> Int
. Dit betekent dat het een functie retourneert, in plaats van een eenvoudige waarde. De functie die het retourneert heeft geen parameters, en retourneert een Int
waarde elke keer dat het wordt aangeroepen.
hier is amount
argument, runningTotal
wordt gedeclareerd als variabele en geïnitialiseerd met 0. Geneste functie incrementer
vangt amount
en runningTotal
uit de omringende context.
laten we makeIncrementer
in Actie bekijken:
opmerking: Als optimalisatie kan Swift in plaats daarvan een kopie van een waarde vastleggen en opslaan als die waarde niet wordt gemuteerd door een sluiting, en als de waarde niet wordt gemuteerd nadat de sluiting is gemaakt.
Swift verzorgt ook al het geheugenbeheer dat betrokken is bij het verwijderen van variabelen wanneer deze niet langer nodig zijn.
om zich te ontdoen van lange afsluiting expressie in functie argument kunt u typealias gebruiken.
niet-ontsnappende sluitingen:
Sluitingsparameters ontsnapten standaard vóór Swift 3. Een sluiting zou niet ontsnappen aan het functielichaam als sluitingsparameters gemarkeerd zijn als niet-ontsnappend
In Swift 3 is het omgekeerd. Wanneer u een sluiting als functieargument passeert, wordt de sluiting uitgevoerd met het lichaam van de functie en geeft de compiler terug. Als de uitvoering eindigt, de gepasseerde sluiting gaat uit het bereik en hebben geen bestaan meer in het geheugen.
het minste dat u moet weten
Afsluitparameters zijn standaard niet-escaping, als u aan de afsluituitvoering wilt ontsnappen, moet u @escaping gebruiken met de afsluitparameters.
levenscyclus van de niet-ontsnappende sluiting:
1. Geef de sluiting door als een functieargument, tijdens de functieaanroep.
2. Doe wat werk in functie en voer vervolgens de sluiting uit.
3. Functie keert terug.
door Beter geheugenbeheer en optimalisaties heeft Swift alle sluitingen standaard veranderd om niet-escaping te zijn. CaptureList.swift
is een voorbeeld van niet-ontsnappende afsluiting.
Note: @non-escaping annotation is alleen van toepassing op functietypen
Escaping Closures:
van een afsluiting wordt gezegd dat deze een functie ontsnapt wanneer de afsluiting wordt doorgegeven als argument aan de functie, maar wordt aangeroepen nadat de functie terugkeert. Het markeren van een sluiting met @escaping
betekent dat u binnen de sluiting expliciet naar self
moet verwijzen.
levenscyclus van de @ escaping sluiting:
1. Geef de sluiting door als functieargument, tijdens de functieaanroep.
2. Doe wat extra werk in functie.
3. Functie voert de sluiting asynchroon of opgeslagen uit.
4. Functie keert terug.
laten we eens kijken waar sluitingen standaard ontsnappen:
- variabelen van het functietype zijn impliciet escaping
- typealiases zijn impliciet escaping
- optionele sluitingen zijn impliciet escaping
veel voorkomende fout:
het toewijzen van niet-escaping closure aan escaping closure. Er zijn 2 manieren om dit op te lossen:
- markeer sluiting als escaping
- of houd het standaard @noescape-gedrag door de sluiting optioneel te maken
Autoclosures:
Swift ‘ s @autoclosure
attribuut stelt u in staat om een argument te definiëren dat automatisch wordt verpakt in een sluiting. Het neemt geen argumenten aan, en als het wordt genoemd, geeft het de waarde terug van de uitdrukking die erin is gewikkeld. Dit syntactische gemak laat je accolades weglaten rond de parameter van een functie door een normale expressie te schrijven in plaats van een expliciete afsluiting.
bijvoorbeeld, de functie assert(condition:message:file:line:)
neemt een autoclosure voor zijn condition
en message
parameters; zijn condition
parameter wordt alleen geëvalueerd in debug builds en zijn message
parameter wordt alleen geëvalueerd als condition
false
is.
func assert(_ expression: @autoclosure () -> Bool,
_ message: @autoclosure () -> String) {}
@autoclosure
gebruiken met @escaping
:
@autoclosure @escaping () -> Bool
sluitingen vs blokken:
“Swift sluitingen en Objective-C blokken zijn compatibel, zodat u Swift sluitingen kunt doorgeven aan Objective – C methoden die blokken verwachten. Swift sluitingen en functies hebben hetzelfde type, zodat u zelfs de naam van een Swift-functie kunt doorgeven. Sluitingen hebben vergelijkbare capture semantiek als blokken, maar verschillen op één belangrijke manier: variabelen zijn veranderlijk in plaats van gekopieerd. Met andere woorden, het gedrag van __block in Objective-C is het standaard gedrag voor variabelen in Swift.”
sluitingen vs gedelegeerden:
de oplossing hangt af van het probleem. Bovendien, Apple is het verschuiven van de focus op Callback patroon. UIAlertAction
is hier een voorbeeld van.
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