Demystifying @escaping, @non-escaping, @autoclosure and curry function
sulkemiset ovat itsenäisiä toimintoja, joita voidaan siirtää ja käyttää koodissa.
– Apple
sulkemiset voivat tallentaa ja tallentaa viittauksia mihin tahansa vakioihin ja muuttujiin siitä kontekstista, jossa ne on määritelty, eli sulkemisesta eli sulkemisesta. Voit ajatella sulkemista funktiona, jolla ei ole omaa nimeä ja joka kaappaa ympäristöstään mitään arvoja. Funktiot ja sulkemiset ovat ensiluokkaisia objekteja Swiftissä: niitä voi tallentaa, siirtää argumentteina funktioille ja käsitellä kuten mitä tahansa muuta arvoa tai objektia. Sulkemisten siirtäminen loppuun käsittelijöinä on yleinen kuvio monissa sovellusliittymissä. Standard Swift-kirjasto käyttää sulkuja lähinnä tapahtumien käsittelyyn ja takaisinsoittoihin.
funktiot ovat itsenäisiä koodinpätkiä, jotka suorittavat tietyn tehtävän. Funktiolle annetaan nimi, joka tunnistaa, mitä se tekee, ja tätä nimeä käytetään ”kutsumaan” funktiota suorittamaan tehtävänsä tarvittaessa. Määrittelet funktion func
hakusanalla. Funktiot voivat ottaa none: n moniin parametreihin, variadisiin parametreihin ja palauttaa none: n tai useita parametreja.
Funktiotyypit
Funktion tyyppi koostuu funktion parametrityypeistä ja paluutyypistä. Yllä olevassa esimerkissä funktion tyyppi on:(Int, Int) -> Int
tämä voidaan lukea seuraavasti: ”funktio, jolla on kaksi parametria, molemmat tyyppiä Int
ja joka palauttaa arvon tyyppiä Int
.”Funktion tyyppi voidaan asettaa parametriksi tai paluutyypiksi funktiolle.
Funktiotyypit voidaan antaa mille tahansa muuttujalle näin:
var mathFunction: (Int, Int) -> Int = add
funktiot ovat sulkemistapauksia. Sulkemiset ovat yksi kolmesta muodosta:
- Globaalit toiminnot: niillä on nimi, eivätkä ne voi kaapata arvoa.
- sisäkkäiset funktiot: niillä on nimi, ja ne voivat kaapata arvoja sulkevasta funktiostaan.
- Sulkulausekkeet: niillä ei ole nimeä ja ne voivat kaapata arvoja ympäröivästä kontekstistaan.
Sulkuilmaisu:
Closure voidaan luoda laittamalla funktiotyyppi curly-henkselien sisään ja in
avainsana palautustyypin perään.
Pikaviittausargumenttien Nimet
Sulkemisargumentit voivat viitata asemaan so. ,
,
,
ja niin edelleen.
implisiittiset palautukset sulkemisesta:
yhden lausekkeen sulkemiset voivat implisiittisesti palauttaa yhden lausekkeen tuloksen jättämällä return
hakusanan pois ilmoituksestaan.
monirivisessä lausekkeessa return
hakusanaa ei voi jättää pois.
Perään Sulkeminen:
jos funktiolle pitää siirtää sulkulauseke, koska funktion viimeinen argumentti ja sulkulauseke on liian pitkä, se voidaan kirjoittaa perään sulkemisena. Funktiokutsun sulkeiden () jälkeen kirjoitetaan perään loppulause, vaikka se on edelleen argumentti funktiolle. Kun käytät perään sulkemisen syntaksia, et kirjoita sulkemisen argumenttimerkintää osana funktiokutsua.
jos sulkeminen on menetelmän viimeinen parametri, swift antaa sinun kirjoittaa näin 🖕
jälkiasennussyntaksin käyttö kiteyttää sulkemisen toiminnot siististi välittömästi sulkemisen tukeman toiminnon jälkeen, eikä sulkemista tarvitse kääriä koko sulkemiseen reduce(_:)
– menetelmän uloimpien sulkujen sisään.
Capturing Values:
sulkemisella voidaan kuvata vakioita ja muuttujia ympäröivästä kontekstista, jossa se on määritelty. Sulkeuma voi sitten viitata ja muuttaa näiden vakioiden ja muuttujien arvoja kehonsa sisältä käsin, vaikka alkuperäistä vakioita ja muuttujia määrittävää ulottuvuutta ei enää olisikaan.
Swiftissä yksinkertaisin sulkemismuoto, jolla voidaan kaapata arvoja, on sisäkkäinen funktio, joka on kirjoitettu toisen funktion kehoon. Sisäkkäinen funktio voi kaapata minkä tahansa ulkofunktionsa argumenteista ja se voi myös kaapata mitä tahansa ulkofunktion sisällä määriteltyjä vakioita ja muuttujia.
tämä makeIncrementer
funktio hyväksyy yhden parametrin eli Int syötteeksi ja palauttaa funktiotyypin eli () -> Int
. Tämä tarkoittaa, että se palauttaa funktion yksinkertaisen arvon sijaan. Funktiolla, jonka se palauttaa, ei ole parametreja, ja se palauttaa arvon Int
joka kerta, kun sitä kutsutaan.
tässä amount
on argumentti, runningTotal
julistetaan muuttujaksi ja alustetaan arvolla 0. Sisäkkäinen funktio incrementer
vangitsee amount
ja runningTotal
ympäröivästä kontekstista.
katsotaan makeIncrementer
toiminnassa:
Huomautus: Optimointina Swift voi sen sijaan kaapata ja tallentaa kopion arvosta, jos kyseinen arvo ei mutatoidu sulkemisella ja jos arvoa ei mutatoida sulkemisen luomisen jälkeen.
Swift hoitaa myös kaiken muistinhallinnan, joka liittyy muuttujien hävittämiseen silloin, kun niitä ei enää tarvita.
funktioargumentin pitkäsulkuisista lausekkeista voi päästä eroon käyttämällä typealioita.
Poistumattomat sulkemiset:
Sulkemisparametrit karkasivat oletusarvoisesti ennen Swift 3: a. Sulkeuma ei poistuisi funktion rungosta, jos sulkemisparametrit on merkitty pakoonpääsemättömiksi
Swift 3: ssa se on peruutettu. Kun ohitat sulkemisen funktion argumenttina, sulkeminen saa suorittaa funktion rungolla ja palauttaa kääntäjän takaisin. Kun toteutus päättyy, kulunut sulkeminen menee pois soveltamisalasta eikä ole enää olemassaoloa muistissa.
vähiten sinun tarvitsee tietää
Sulkemisparametrit ovat oletusarvoisesti pakenemattomia, jos haluat paeta sulkemistehtävää, sinun on käytettävä @escaping sulkemisparametrien kanssa.
karkaamattoman sulkemisen elinkaari:
1. Siirrä sulkeminen funktion argumenttina funktiokutsun aikana.
2. Tee työtä funktiossa ja suorita sitten sulkeminen.
3. Funktio palaa.
paremman muistinhallinnan ja optimointien ansiosta Swift on muuttanut kaikki sulkemiset oletusarvoisesti pakenemattomiksi. CaptureList.swift
on esimerkki pakenemattomasta sulkemisesta.
Huomautus: @non-escaping annotation koskee vain funktiotyyppejä
Escaping closes:
sulkemisen sanotaan karkaavan funktiolta, kun sulkeuma välitetään argumenttina funktiolle, mutta sitä kutsutaan funktion palautuksen jälkeen. Sulkemisen merkitseminen merkinnällä @escaping
tarkoittaa, että sulkemisen yhteydessä on viitattava nimenomaisesti numeroon self
.
Lifecycle of the @escaping closure:
1. Siirrä sulkeminen funktioargumenttina funktiokutsun aikana.
2. Tee lisätyötä funktiossa.
3. Toiminto suorittaa sulkeminen asynkronisesti tai tallennettu.
4. Funktio palaa.
katsotaan, mihin sulkemiset lähtökohtaisesti karkaavat:
- funktiotyypin muuttujat ovat implisiittisiä karkaamisia
- typealiaset ovat implisiittisiä karkaamisia
- vapaaehtoiset sulkemiset ovat implisiittisiä karkaamisia
yleinen virhe:
Pakoonpääsemättömiä sulkemisia. On 2 tapoja korjata tämä:
- merkitse sulkeminen pakenemiseksi
- tai pidä @ noescape-oletusarvo tekemällä sulkemisesta valinnainen
Autoclosures:
Swiftin @autoclosure
– attribuutin avulla voit määritellä argumentin, joka automaattisesti kietoutuu sulkemiseen. Se ei vaadi argumentteja, ja kun sitä kutsutaan, se palauttaa sen sisään käärityn ilmaisun arvon. Tämä syntaktinen mukavuutta voit jättää henkselit noin funktion parametrin kirjoittamalla normaalin lausekkeen sijaan nimenomainen sulkeminen.
esimerkiksi assert(condition:message:file:line:)
funktio vaatii autoklosuurin sen condition
ja message
parametreille; sen condition
parametri arvioidaan vain debug-rakenteissa ja sen message
parametri arvioidaan vain, jos condition
on false
.
func assert(_ expression: @autoclosure () -> Bool,
_ message: @autoclosure () -> String) {}
käyttää @autoclosure
kanssa @escaping
attribuutin syntaksi on:
@autoclosure @escaping () -> Bool
sulkemiset vs lohkot:
”Swift-sulkemiset ja Objective-C-lohkot ovat yhteensopivia, joten Swift-sulkemiset voi siirtää Objective-C-menetelmiin, jotka odottavat blokkeja. Swift-sulkimet ja toiminnot ovat samantyyppisiä, joten voit jopa siirtää Swift-funktion nimen. Suluissa on samanlainen kaappaussemantiikka kuin lohkoissa, mutta ne eroavat toisistaan yhdellä keskeisellä tavalla: muuttujat ovat muunneltavissa sen sijaan, että ne kopioitaisiin. Toisin sanoen __lohkon käyttäytyminen Objective-C: ssä on muuttujien oletuskäyttäytyminen Swiftissä.”
lakkautukset vs. valtuutetut:
ratkaisu riippuu ongelmasta. Lisäksi Apple on siirtämässä painopistettään Takaisinkutsukuvioon. UIAlertAction
on esimerkki tästä.
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