Strach sa pomaly nastavil, keď som si uvedomil, že z týchto sériových fotiek dochádzam

Swift + inicializácia s uzávermi

Uzávery F.T.W.

Stručná poznámka - všetky moje budúce príspevky sa uverejnia na mojej špecializovanej webovej stránke a táto publikácia sa už neaktualizuje. Vďaka za prečítanie!

Celý začiatočný tanec začínam kopať vo Swift. Napísal som o tom. Písal som o tom, prečo to dokonca funguje tak, ako to funguje. Hovoril som o tom. Čítal som o tom (veľa). Ale hej, som späť za jeden ďalší akt v tejto veci.

Zo všetkých mnohých krásnych a rozmanitých spôsobov, ako je možné niečo inicializovať v službe Swift - používanie uzáverov sa zvyčajne nevyvíja ako metóda, ako to urobiť. Ale bohužiaľ, môže spôsobiť, že kód kotlovej dosky init () bude oveľa menej bolestivý a trochu zvládnuteľný.

Pre programové užívateľské rozhranie tu existuje - to pre vás !

UIKit == UIHugeSetupCode ()

Pozri, nie je to chyba UIKits. Komponenty, s ktorými musí používateľ interagovať, sa môžu prenajať na hornú časť inštalačného kódu, pretože preferencie. Veľa z toho sa zvyčajne nachádza v viewDidLoad alebo loadView:

prepísať func loadView ()
{
    nechať helloWorldLbl = UILabel ()
    helloWorldLbl.text = NSLocalizedString (“controller.topLbl.helloWorld”, komentár: “Hello World!”)
    helloWorldLbl.font = UIFont.preferredFontForTextStyle (UIFontTextStyleBody)
    helloWorldLbl.textColor = UIColor.whiteColor ()
    helloWorldLbl.textAlignment = .Center
    self.view.addSubview (helloWorldLbl)
}

Toto je celkom štandardné pre tých z nás, ktorí sa púšťajú do vôd Cocoa Touch bez toho, aby boli na dohľad .xib alebo .storyboard. Aj keď, ak zdieľate moju lásku k nepatrným metódam viewDidLoad alebo loadView, môžete to odložiť inde.

Povedzme, že nehnuteľnosť:

nechaj helloWorldLbl: UILabel = {
    nech lbl = UILabel ()
    lbl.text = NSLocalizedString (“controller.topLbl.helloWorld”, komentár: “Hello World!”)
    lbl.font = UIFont.preferredFontForTextStyle (UIFontTextStyleBody)
    lbl.textColor = UIColor.whiteColor ()
    lbl.textAlignment = .Center
    návrat lbl
} ()

Pretty. Vo vlastnej knihe spoločnosti Apple o aplikácii Swift sa uvádza, že „ak predvolená hodnota vašej nehnuteľnosti vyžaduje určité prispôsobenie alebo nastavenie, môžete použiť uzavretie alebo globálnu funkciu na poskytnutie prispôsobenej predvolenej hodnoty pre túto vlastnosť.“ Ako sme práve spomenuli, výnos UIKit riadi výnos veľa prispôsobenia a nastavenia.

Jedným z pekných vedľajších produktov je však to, ako loadView vyzerá teraz:

prepísať func loadView
{
    self.view.addSubview (self.helloWorldLbl)
}

Berte však na vedomie „()“ na konci uzávierky majetkového priznania. Týmto necháte malých sprievodcov Swift, ktorí zostavujú váš kód, vedieť, že inštancia je priradená k návratovému typu uzávierky. Keby sme to vynechali, je možné, že by sme k inštancii mohli priradiť aj samotné uzavretie.

A v tomto prípade to je .

Pravidlá sú pravidlá

Aj keď máme novú žiarivú hračku, je nevyhnutné pamätať na pravidlá krajiny. Keďže priraďujeme vlastníctvo k uzávierke, pravdepodobne ešte nebola inicializovaná zvyšná časť inštancie, ktorá obsahovala. Z tohto dôvodu, keď sa uzávierka spustí, nie je možné v rámci nej odkazovať na iné hodnoty majetku ani na seba.

Napríklad:

nechaj helloWorldLbl: UILabel = {
    nech lbl = UILabel ()
    lbl.text = self.someFunctionToDetermineText () // Chyba kompilátora
    lbl.font = UIFont.preferredFontForTextStyle (UIFontTextStyleBody)
    lbl.textColor = self.myAppTheme.textColor () // Ďalšia chyba
    lbl.textAlignment = .Center
    návrat lbl
} ()

Inštancia seba samého nemusí byť bezpečná, alebo sa nemusí uskutočniť dvojfázovým inicializačným procesom spoločnosti Swift. To isté skutočne platí pre všetky vlastnosti inštancie, ktoré môžu alebo nemusia byť pridelené a inicializované, pretože ukončenie sa vykoná okamžite.

Toto je zreteľná, ale oprávnená nevýhoda pri použití uzáverov na inicializáciu. Dáva to však úplne zmysel - a je to v súlade s jedným z troch cieľov dizajnu Swift: bezpečnosť.

Získajte roztomilé zbierky

Jednou z oblastí, kde som túto techniku ​​považoval za obzvlášť užitočnú, sú prípady, ktoré predstavujú jednu z mnohých rôznych foriem zbierky v službe Swift. Z mnohých talentov Swift je krájanie a preosievanie prostredníctvom zbierok s výkonom tisíc titanov jedným z mojich najobľúbenejších.

Zoberme si nasledujúci príklad získaný z inicializátora v projekte, na ktorom práve pracujem. Trieda, v ktorej je uložený tento kód, má vlastníctvo [Developer]. Pri novom štarte som nastavil ich počiatočné hodnoty zo súboru .plist. Potom sú uložené prostredníctvom NSKeyedArchiver.

guard let devs = NSKeyedUnarchiver.unarchiveObjectWithFile (DevDataManager.ArchiveURL.path!) ako? [Vývojár] inde
{
    self.developers = {
        nech pListData = // Získať plistické údaje
        var devArray: [Developer] = [Developer] ()
        // Nastaviť devArray z údajov o zozname
        return devArray.map {$ 0.setLocation ()}
                       .filter {$ 0.isRentable}
                       .sort {$ 0.name <$ 1.name}
     } ()
    spiatočný
}
samostatne sa vyvíjajúci = devs

Tento prístup sa mi veľmi páči, pretože hoci ho nepoužívame mimo inicializátora, zámer kódu je veľmi jasný v tom, že je zodpovedný iba za nastavenie vlastníctva.

Keď sa inicializátory a nahradenia viewDidLoad zväčšujú, rozdeľovanie takýchto vecí (prinajmenšom) je vítaným darčekom z hľadiska čitateľnosti.

Získanie NSCute

Ak ste skutočne len vykopali inicializáciu vecí pomocou uzávierky, ale trpíte vážnym nedostatkom používania týchto funkčných $ v kóde, rozveselte sa. Pomocou nejakého adept Swiftery je možné vytvoriť nejaký kód, ktorý vyvodí typ v samotnom uzávere, čo vedie k určitej konfigurácii pro štýlu. Zvážte tento kód, s ktorým som sa prvýkrát stretol na vždy informačnom serveri NSHipster:

@warn_unused_result
public func Init  (hodnota: Type, @noescape block: (objekt: Type) -> Void) -> Type
{
    blok (objekt: hodnota)
    návratová hodnota
}

Páči sa mi, kam to ide. Verejná funkcia, ktorá uzavrie typizovaný objekt pomocou generík, ktorý potom vráti tento typ. To znamená, že by ste sa mohli otočiť a inicializovať veci pomocou ďalších informácií o type. Naša prvá vzorka kódu by potom zase vyzerala takto:

nech helloWorldLbl = Init (UILabel ()) {
    $ 0.text = NSLocalizedString (“controller.topLbl.helloWorld”, komentár: “Hello World!”)
    $ 0.font = UIFont.preferredFontForTextStyle (UIFontTextStyleBody)
    $ 0.textColor = UIColor.whiteColor ()
    $ 0.textAlignment = .Center
}

Aj keď sa môže zdať fantázia, skutočne zabraňuje potrebe premennej inštancie z uzáveru a zbavuje sa požiadavky „()“. Veľmi pekné .

Záverečné myšlienky

Dalo by sa povedať, že použitie takejto techniky je šesť v jednej ruke a pol tuctu v druhej. Aj keď je pravda, že riadky kódu, ktoré vytvoril programátor, zostávajú do značnej miery rovnaké, tvrdím, že jeho umiestnenie a flexibilita ho robia ideálnym pre mnohé scenáre.

Je to zábavný spôsob, ako veci urobiť, a dokonca aj niekoľko spôsobov, ako urobiť to isté v našom starom priateľovi Objective-C. Ale hej, čím viac vieš, amirite?

Do nasledujúceho týždňa = {let týždeň = týždeň () týždeň.rozšírenýBy (dni: 7)} ()

Jordan Morgan je softvérový inžinier pre iOS, ktorý prevádzkuje program Dreaming In Binary

Ak ste sa dozvedeli o používaní uzávierok pre inicializátory, neváhajte a pokračujte a odporúčame NSR (tu: nižšie);