Hvad betyder @escaping og @nonescaping lukninger i Swift?

Under koden kan du, hver gang du arbejder med funktionerne, have kørt med @escaping- eller @nonescaping-attributterne. Har du nogensinde givet tid til at tænke over, hvad det betyder? Så her skal vi diskutere disse vilkår.

Hvad er lukninger?

Lukninger er selvstændige blokke af funktionalitet, der kan sendes rundt og bruges i din kode.

I Swift 1.x og Swift 2.x var lukningsparameteren @escaping som standard, hvilket betyder, at lukning kan undslippe under udførelsen af ​​funktionskroppen. hvis du ikke ønsker at undslippe lukningsparametre, markér det som @nonescaping.

I Swift 3.x foretaget Apple en ændring: lukningsparametre blev @nonescaping som standard, lukning udføres også med funktionslegemet, hvis man vil undslippe udførelse af lukning markerer det som @escaping. Hvorfor Apple foretaget denne ændring? Lad os diskutere dette i slutningen af ​​diskussionen .

1. @ nonescaping lukninger:

Når du passerer en lukning som funktionsargument, udføres lukningen med funktionens krop og returnerer kompilatoren tilbage. Efterhånden som henrettelsen slutter, går den afsluttede lukning ud af anvendelsesområdet og har ikke mere eksistens i hukommelsen.

Livscyklus af @nonescaping-lukningen:
 1. Overfør lukningen som funktionsargument under funktionsopkaldet.
 2. Udfør noget ekstra arbejde med funktion.
 3. Funktion kører lukningen.
 4. Funktion returnerer kompilatoren tilbage.

Eksempel:

func getSumOf (matrix: [Int], handler: ((Int) -> Void)) {
        // trin 2
        var sum: Int = 0
        for værdi i matrix {
            sum + = værdi
        }
        
        // trin 3
        handleren (sum)
    }
    
    func doSomething () {
        // sætp 1
        self.getSumOf (array: [16.756.442,63]) {[svagt selv] (sum) i
            print (sum)
            // trin 4, færdiggørelse af udførelsen
        }
    }
// Det udskriver summen af ​​alle de givne numre.

Her kaldte vi netop funktionen med en lukning, der udføres i slutningen af ​​funktionens krop.
Så vi slipper ikke for gennemførelsen af ​​lukningen. Når trin 4 udføres, vil lukning ikke have nogen eksistens i hukommelsen.

2. @ afskærmning af lukninger:

Når man passerer en lukning som funktionsargument, bevares lukningen for at blive udført senere, og funktionens krop udføres, returnerer compileren tilbage. Når udførelsen slutter, findes omfanget af den beståede lukning og har eksistens i hukommelsen, indtil lukningen bliver udført.
 Der er flere måder at undslippe lukningen på:

  • Lagring: Når du har brug for at bevare lukningen i lageret, der findes i hukommelsen, udføres fortiden til den opkaldsfunktion og returnerer kompilatoren tilbage. (Kan lide at vente på API-svaret)
  • Asynkron udførelse: Når du udfører lukningen asynkront i forsendelseskøen, holder køen lukningen i hukommelsen for dig, der skal bruges i fremtiden. I dette tilfælde har du ingen idé om, hvornår lukningen vil blive henrettet.

Når du prøver at bruge lukningen med disse indstillinger, viser den hurtige kompilator fejlen.

Livscyklus af @escaping-lukningen:
1. Overfør lukningen som funktionsargument under funktionsopkaldet.
2. Udfør noget ekstra arbejde i funktion.
3. Funktion udfør lukningen asynkront eller gemt.
4. Funktion returnerer kompilatoren tilbage.

Eksempel 1 (Opbevaring):

var komplitionHandler: ((Int) -> Void)?
    func getSumOf (matrix: [Int], handler: @escaping ((Int) -> Void)) {
        // trin 2
       // her tager jeg f.eks. loop, men i virkeligheden vil det være noget andet som API-opkald
       var sum: Int = 0
        for værdi i matrix {
            sum + = værdi
        }
// trin 3
        self.complitionHandler = handler
    }
    
    func doSomething () {
        // sætp 1
        self.getSumOf (array: [16.756.442,63]) {[svagt selv] (sum) i
            print (sum)
            // trin 4, færdiggørelse af udførelsen
        }
    }
// Her opbevarer vi lukningen til fremtidig brug.
// Det udskriver summen af ​​alle de passerede numre.

Eksempel 2 (asynkron udførelse):

func getSumOf (matrix: [Int], handler: @escaping ((Int) -> Void)) {
        // trin 2
        var sum: Int = 0
        for værdi i matrix {
            sum + = værdi
        }
        // trin 3
        Globals.delay (0.3, lukning: {
            handleren (sum)
        })
    }
    
    func doSomething () {
        // sætp 1
        self.getSumOf (array: [16.756.442,63]) {[svagt selv] (sum) i
            print (sum)
            // trin 4, afsluttende udførelse
        }
    }
// Her kalder vi lukningen med en forsinkelse på 0,3 sekunder
// Det udskriver summen af ​​alle de passerede numre.

Her er vi med betydningen af ​​@escaping-attributten. Så når du har brug for at undslippe udførelsen af ​​lukningen, skal du bruge @escaping-attributten i Swift 3. Ovennævnte vist fejl i compiler forsvinder efter lukning som undslip ved hjælp af attributten @escaping.

Hvorfor lavede @nonescaping som standard?

Der er mange forskellige fordele ved at gøre ikke-undslippe som standard. De vigtigste fordele er ydelse og kodeoptimering af kompilatoren, fordi hvis kompilatoren ved, at lukningen ikke slipper ud, vil den sørge for hukommelsesallokering til lukningen.

Og en anden er, at vi kan bruge selv uden problemer i ikke-undslipende lukninger, fordi lukningen udføres, før funktionen vender tilbage, så selvet vil være der helt sikkert. Vi behøver ikke at bruge svagt selv, dette er den ekstra funktion der .

I Swift 3 lukker lukninger som standard ikke, kan vi bruge @escaping, hvis ikke, hvad vi ønsker. Ikke-undslipende lukning defiently vil udføres, før funktionen vender tilbage.
Husk altid at bruge svagt selv, mens du bruger en lukning.

Tak, fordi du læser, tryk venligst på anbefalingsikonet, hvis du kan lide denne samling . Spørgsmål? Efterlad dem i kommentaren.