Hva betyr @escaping og @nonescaping nedleggelser i Swift?

Under koden kan du, når du arbeider med funksjonene, ha kjørt med @escaping- eller @nonescaping-attributtene. Har du noen gang gitt tid til å tenke på, hva det betyr? Så her skal vi diskutere om disse begrepene.

Hva er stengninger?

Lukkinger er selvstendige blokker av funksjonalitet som kan føres rundt og brukes i koden din.

I Swift 1.x og Swift 2.x var lukningsparameteren @escaping som standard, betyr at lukking kan slippe ut under utførelsen av funksjonskroppen. Hvis du ikke vil unnslippe stengingsparametere, merk det som @nonescaping.

I Swift 3.x gjorde Apple en endring: lukkingsparametere ble @nonescaping som standard, lukking vil også bli utført med funksjonsorganet, hvis du vil slippe utførelse av lukking markerer det som @escaping. Hvorfor Apple gjorde denne endringen? La oss diskutere dette på slutten av diskusjonen .

1. @nonescaping nedleggelser:

Når du passerer en nedleggelse som funksjonsargument, blir lukkingen utført med funksjonens kropp og returnerer kompilatoren tilbake. Når henrettelsen avsluttes, går den passerte nedleggelsen utenfor omfanget og har ikke mer eksistens i minnet.

Livssyklus for stengelsen av @nonescaping:
 1. Gi nedleggelsen som funksjonsargument under funksjonssamtalet.
 2. Gjør litt tilleggsarbeid med funksjon.
 3. Funksjon kjører stengingen.
 4. Funksjon returnerer kompilatoren tilbake.

Eksempel:

func getSumOf (matrise: [Int], handler: ((Int) -> Void)) {
        //steg 2
        var sum: Int = 0
        for verdi i matrise {
            sum + = verdi
        }
        
        // trinn 3
        håndterer (sum)
    }
    
    func doSomething () {
        // settp 1
        self.getSumOf (matrise: [16 756 442,6,23]) {[svakt selv] (sum) i
            print (sum)
            // trinn 4, etterbehandling
        }
    }
// Den vil skrive ut summen av alle oppgitte tall.

Her kalte vi bare funksjonen med en nedleggelse, som blir utført på slutten av funksjonen.
Så vi slipper ikke unna utførelsen av nedleggelsen. Ettersom trinn 4 blir utført vil ikke nedleggelse ha noen eksistens i minnet.

2. @ lukker ned:

Når du passerer en nedleggelse som funksjonsargument, blir bevaringen holdt for å bli utført senere, og funksjonen til kroppen blir utført, returnerer kompilatoren tilbake. Når henrettelsen avsluttes, eksisterer omfanget av vedtatt stenging og har eksistens i minnet, inntil nedleggelsen blir henrettet.
 Det er flere måter å slippe unna stengingen:

  • Lagring: Når du trenger å bevare stengningen i lagring som finnes i minnet, blir tidligere av anropsfunksjonen utført og returnere kompilatoren tilbake. (Som å vente på API-svaret)
  • Asynkron utførelse: Når du utfører stengingen asynkront i forsendelseskø, vil køen holde lukkingen i minnet for deg, som skal brukes i fremtiden. I dette tilfellet har du ingen anelse om når nedleggelsen vil bli henrettet.

Når du prøver å bruke lukkingen med dette alternativet, viser den hurtige kompilatoren feilen.

Livssyklus av @escaping-stengingen:
1. Gi nedleggelsen som funksjonsargument under funksjonssamtalet.
2. Gjør litt tilleggsarbeid i funksjon.
3. Funksjon utføre stengingen asynkront eller lagret.
4. Funksjon returnerer kompilatoren tilbake.

Eksempel 1 (lagring):

var komplitionHandler: ((Int) -> Void)?
    func getSumOf (matrise: [Int], handler: @escaping ((Int) -> Void)) {
        //steg 2
       // her tar jeg for eksempel bare loop, i virkeligheten vil det være noe annet som API-anrop
       var sum: Int = 0
        for verdi i matrise {
            sum + = verdi
        }
// trinn 3
        self.complitionHandler = handler
    }
    
    func doSomething () {
        // settp 1
        self.getSumOf (matrise: [16 756 442,6,23]) {[svakt selv] (sum) i
            print (sum)
            // trinn 4, fullførelse av utførelsen
        }
    }
// Her lagrer vi nedleggelsen for fremtidig bruk.
// Det vil skrive ut summen av alle passerte tall.

Eksempel 2 (asynkron utførelse):

func getSumOf (matrise: [Int], handler: @escaping ((Int) -> Void)) {
        //steg 2
        var sum: Int = 0
        for verdi i matrise {
            sum + = verdi
        }
        // trinn 3
        Globals.delay (0.3, nedleggelse: {
            håndterer (sum)
        })
    }
    
    func doSomething () {
        // settp 1
        self.getSumOf (matrise: [16 756 442,6,23]) {[svakt selv] (sum) i
            print (sum)
            // trinn 4, etterbehandling
        }
    }
// Her kaller vi nedleggelsen med en forsinkelse på 0,3 sekunder
// Det vil skrive ut summen av alle passerte tall.

Her er vi med betydningen av @escaping-attributtet. Når du trenger å unnslippe utførelsen av lukkingen, bruker du @escaping-attributtet i Swift 3. Ovennevnte feil i kompilatoren vil forsvinne etter at du har gjort lukking som rømming ved å bruke @escaping-attributtet.

Hvorfor laget de @nonescaping som standard?

Det er mange forskjellige fordeler med å gjøre ikke-rømming som standard. De viktigste fordelene er ytelse og kodeoptimalisering av kompilatoren, fordi hvis kompilatoren vet at lukkingen ikke slipper til, vil han ta seg av minnetildelingen for nedleggelsen.

Og en annen er at vi kan bruke selvbilde uten problemer i ikke-rømrende stenginger fordi stengingen utføres før funksjonen kommer tilbake slik at jeget vil være der med sikkerhet. Vi trenger ikke bruke svakt selvtillit. Dette er tilleggsfunksjonen til det .

I Swift 3 lukker ikke stengningene som standard, kan du bruke @escaping hvis ikke det vi ønsker. Stenging som ikke unnslipper trassløst vil kjøres før funksjonen kommer tilbake.
Remember Husk alltid å bruke svakt selv når du bruker en lukking.

Takk for at du leser, trykk på anbefalingsikonet hvis du liker denne samlingen . Spørsmål? Legg igjen dem i kommentaren.