Demystifikací @útěku, @non-unikat, @autoclosure a kari funkce
Uzávěry jsou samostatné bloky funkcí, které mohou být předány kolem a použít v kódu.
– Apple
uzávěry mohou zachytit a ukládat odkazy na jakékoli konstanty a proměnné z kontextu, ve kterém jsou definovány, známé jako uzavření nad uzavřením. Můžete si představit uzavření jako funkci, která nemá vlastní název a zachycuje jakékoli hodnoty ze svého prostředí. Funkce a uzávěry jsou prvotřídní objekty v Swift: můžete ukládat, předávat je jako parametry do funkcí, a zacházet s nimi jako jakékoli jiné hodnoty nebo objekt. Předávání uzávěrů jako zpracovatelů dokončení je běžným vzorem v mnoha API. Standardní knihovna Swift používá uzávěry většinou pro zpracování událostí a zpětné volání.
funkce jsou samostatné bloky kódu, které provádějí konkrétní úkol. Dáte funkci název, který identifikuje, co dělá, a tento název se používá k „volání“ funkce, aby v případě potřeby vykonala svůj úkol. Definujete funkci pomocí klíčového slova func
. Funkce mohou mít žádný na mnoho parametrů, variadické parametry a vrátit žádné nebo více parametrů.
Typy Funkcí
typ Funkce je tvořena typy parametrů a návratový typ funkce. Pro výše uvedený příklad, funkce typ je:(Int, Int) -> Int
To lze číst jako: „funkce, která má dva parametry, oba typu Int
a, která vrací hodnotu typu Int
.“Typ funkce lze nastavit jako parametr nebo návratový typ funkce.
typy funkcí lze přiřadit libovolné proměnné, jako je tato:
var mathFunction: (Int, Int) -> Int = add
funkce jsou zvláštní případy uzavření. Uzávěry mají jednu ze tří podob:
- globální funkce: mají jméno a nemohou zachytit hodnotu.
- vnořené funkce: mají název a mohou zachytit hodnoty ze své uzavírací funkce.
- uzavírací výrazy: nemají název a mohou zachytit hodnoty z okolního kontextu.
Uzavírací Výraz:
Uzavření může být vytvořen tím, že typ funkce uvnitř složených závorek a in
klíčové slovo po návratový typ.
Zkratka Jména Argumentů
Uzavření argumenty mohou odkazovat na pozici, tj. ,
,
,
a tak dále.
Implicitní Výnosy z Uzavření:
Single-výraz uzávěry mohou implicitně vrátí výsledek jejich jediný výraz vynecháním return
klíčové slovo z jejich prohlášení.
Pro víceřádkový výraz, uzavření, return
klíčové slovo nemůže být vynechán.
Koncové Uzavření:
pokud potřebujete funkci předat uzavírací výraz jako poslední argument funkce a uzavírací výraz je příliš dlouhý, lze jej zapsat jako koncový uzávěr. Koncové uzavření je zapsáno za závorkami volání funkce (), i když je to stále argument pro funkci. Když použijete syntaxi koncového uzavření, nepíšete štítek argumentu pro uzavření jako součást volání funkce.
Pokud uzávěr je poslední parametr metody, pak swift umožňuje psát takhle 🖕
použití koncové uzavření syntaxe přehledně vystihuje uzavření funkčnost okamžitě po funkci, která podporuje uzavření, aniž byste museli zabalit celou uzavření rámci reduce(_:)
metoda vnější závorky.
zachycení hodnot:
uzávěr může zachytit konstanty a proměnné z okolního kontextu, ve kterém je definován. Uzávěr pak může odkazovat na a měnit hodnoty těchto konstant a proměnných z jeho těla, i když původní rozsah, který definoval konstanty a proměnné, již neexistuje.
ve Swiftu je nejjednodušší formou uzávěru, který dokáže zachytit hodnoty, vnořená funkce, zapsaná v těle jiné funkce. Vnořená funkce může zachytit některý z argumentů své vnější funkce a může také zachytit všechny konstanty a proměnné definované v rámci vnější funkce.
tato funkce makeIncrementer
přijímá jako vstup jeden argument, tj. To znamená, že vrací funkci, spíše než jednoduchou hodnotu. Funkce, kterou vrací, nemá žádné parametry a vrací hodnotu Int
pokaždé, když je vyvolána.
zde amount
je argument, runningTotal
je deklarován jako proměnná a inicializován 0. Vnořená funkce incrementer
zachycuje amount
a runningTotal
z okolního kontextu.
podívejme se makeIncrementer
v akci:
Poznámka: Jako optimalizace, Swift může místo toho zachytit a uložit kopii hodnotu, pokud hodnota není zmutovaný o uzavření, a pokud není hodnota zmutoval po uzavření je vytvořen.
Swift také zpracovává veškerou správu paměti zapojenou do likvidace proměnných, když již nejsou potřeba.
Chcete-li se zbavit výrazu dlouhého uzavření v argumentu funkce, můžete použít typealias.
Neunikající uzávěry:
parametry uzavření byly ve výchozím nastavení escapovány před Swift 3. Uzavření by neuniklo tělu funkce, pokud jsou parametry uzavření označeny jako neunikající
v Swift 3 bylo obráceno. Když předáváte uzávěr jako argument funkce, uzávěr se spustí s tělem funkce a vrátí kompilátor zpět. Jak exekuce končí, předané uzavření se vymyká rozsahu a již nemá v paměti žádnou existenci.
nejméně, co potřebujete vědět
parametry uzavření jsou ve výchozím nastavení neunikající, pokud chcete uniknout provedení uzavření, musíte použít @escaping s parametry uzavření.
životní cyklus neunikajícího uzávěru:
1. Předejte uzávěr jako parametr funkce během volání funkce.
2. Proveďte nějakou práci ve funkci a poté proveďte uzavření.
3. Funkce se vrací.
díky lepší správě a optimalizaci paměti Swift změnil všechny uzávěry tak, aby ve výchozím nastavení neunikaly. CaptureList.swift
je příkladem neunikajícího uzavření.
Poznámka: @non-escaping anotace se vztahuje pouze na typy funkcí
Escaping uzávěry:
říká se, že uzávěr uniká funkci, když je uzávěr předán jako argument funkci, ale je volán po návratu funkce. Označení uzávěru @escaping
znamená, že musíte v rámci uzávěru výslovně odkazovat na self
.
životní cyklus @escaping closure:
1. Předejte uzavření jako parametr funkce během volání funkce.
2. Proveďte další práci ve funkci.
3. Funkce vykonat uzávěr asynchronně nebo uloženy.
4. Funkce se vrací.
podívejme se, kde jsou uzávěry ve výchozím nastavení escaping:
- Proměnné typu funkce jsou implicitní útěku
- typealiases jsou implicitní útěku
- Volitelné uzávěry jsou implicitní útěku
častá Chyba:
Přiřazení non-útěk uzavření na útěku uzavření. Existují 2 způsoby, jak to opravit:
- Mark uzavření úniku,
- Nebo ponechat výchozí @noescape chování tím, že uzavření volitelné
Autoclosures:
Swift @autoclosure
atribut umožňuje definovat argument, že automaticky dostane zabalené v uzavření. Nevyžaduje žádné argumenty, a když je volán, vrací hodnotu výrazu, který je uvnitř zabalen. Tato syntaktická výhoda umožňuje vynechat závorky kolem parametru funkce napsáním normálního výrazu místo explicitního uzavření.
například, assert(condition:message:file:line:)
funkce trvá autoclosure pro své condition
a message
parametry; condition
parametr je hodnocen pouze v sestavení ladění a jeho message
parametr je hodnocen pouze v případě, condition
false
.
func assert(_ expression: @autoclosure () -> Bool,
_ message: @autoclosure () -> String) {}
použití @autoclosure
s @escaping
syntax atributu je:
@autoclosure @escaping () -> Bool
uzávěry vs bloky:
„rychlé uzávěry a bloky Objective-C jsou kompatibilní, takže můžete předat rychlé uzávěry metodám Objective-C, které očekávají bloky. Uzávěry a funkce Swift mají stejný typ, takže můžete dokonce předat název funkce Swift. Uzávěry mají podobnou sémantiku zachycení jako bloky, ale liší se jedním klíčovým způsobem: proměnné jsou spíše proměnlivé než kopírované. Jinými slovy, chování _ _ block v Objective-C je výchozí chování proměnných v Swift.“
uzávěry vs delegáti:
řešení závisí na problému. Apple navíc přesouvá své zaměření na vzor zpětného volání. UIAlertAction
je toho příkladem.
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