Wat betekenen @escaping en @nonescaping sluitingen in Swift?

Tijdens de code kan het zijn dat u, wanneer u met de functies werkt, met de kenmerken @escaping of @nonescaping hebt gewerkt. Heb je ooit tijd gehad om over na te denken, wat het betekent? Dus hier gaan we het hebben over deze voorwaarden.

Wat zijn sluitingen?

Sluitingen zijn op zichzelf staande blokken van functionaliteit die kunnen worden doorgegeven en gebruikt in uw code.

In Swift 1.x en Swift 2.x was de sluitparameter standaard @escaping, wat betekent dat sluiting kan ontsnappen tijdens de uitvoering van de functie. als u niet wilt ontsnappen aan afsluitingsparameters, markeert u het als @nonescaping.

In Swift 3.x bracht Apple een wijziging aan: sluitingsparameters werden standaard @nonescaping, sluiting wordt ook uitgevoerd met de functielichaam, als u wilt ontsnappen aan de uitvoering van de afsluiting, markeer het dan als @escaping. Waarom heeft Apple deze wijziging aangebracht? Laten we dit aan het einde van de discussie bespreken .

1. @nonescaping sluitingen:

Wanneer een sluiting wordt doorgegeven als het functieargument, wordt de sluiting uitgevoerd met het hoofdgedeelte van de functie en keert de compiler terug. Naarmate de uitvoering eindigt, gaat de doorgegeven sluiting buiten bereik en bestaat deze niet meer in het geheugen.

Levenscyclus van de @nonescaping-sluiting:
 1. Geef de afsluiting als functieargument door tijdens de functieaanroep.
 2. Doe wat extra werk met de functie.
 3. Functie voert de sluiting uit.
 4. Functie retourneert de compiler terug.

Voorbeeld:

func getSumOf (array: [Int], handler: ((Int) -> Void)) {
        //stap 2
        var sum: Int = 0
        voor waarde in array {
            som + = waarde
        }
        
        //stap 3
        handler (sum)
    }
    
    func doSomething () {
        // setp 1
        self.getSumOf (array: [16.756.442,6,23]) {[zwak zelf] (som) in
            druk (sum)
            // stap 4, de uitvoering voltooien
        }
    }
// Het drukt de som van alle gegeven nummers af.

Hier noemden we de functie met een sluiting, die wordt uitgevoerd aan het einde van het lichaam van de functie.
We ontsnappen dus niet aan de uitvoering van de sluiting. Als stap 4 uitgevoerd wordt, zal er geen sluiting in het geheugen bestaan.

2. @escaping sluitingen:

Wanneer een sluiting wordt doorgegeven als het functieargument, wordt de sluiting behouden om later te worden uitgevoerd en wordt de body van de functie uitgevoerd, keert de compiler terug. Als de uitvoering eindigt, bestaat de reikwijdte van de doorgegeven sluiting en bestaat deze in het geheugen, totdat de sluiting wordt uitgevoerd.
 Er zijn verschillende manieren om aan de sluiting te ontsnappen:

  • Opslag: wanneer u de sluiting in de opslag die in het geheugen bestaat, wilt behouden, wordt het verleden van de aanroepfunctie uitgevoerd en keert de compiler terug. (Zoals wachten op de API-reactie)
  • Asynchrone uitvoering: wanneer u de afsluiting asynchroon uitvoert in de verzendwachtrij, houdt de wachtrij de sluiting in het geheugen voor u vast, zodat deze in de toekomst kan worden gebruikt. In dit geval hebt u geen idee wanneer de sluiting wordt uitgevoerd.

Wanneer u de sluiting met deze optie probeert te gebruiken, geeft de snelle compiler de fout weer.

Levenscyclus van de @escaping-sluiting:
1. Geef de afsluiting als functieargument door tijdens de functieaanroep.
2. Doe wat extra werk in functie.
3. Functie voert de sluiting asynchroon of opgeslagen uit.
4. Functie retourneert de compiler terug.

Voorbeeld 1 (opslag):

var complitionHandler: ((Int) -> Nietig)?
    func getSumOf (array: [Int], handler: @escaping ((Int) -> Void)) {
        //stap 2
       // hier neem ik bijvoorbeeld een lus, in het echte geval zal het iets anders zijn zoals een API-aanroep
       var sum: Int = 0
        voor waarde in array {
            som + = waarde
        }
//stap 3
        self.complitionHandler = handler
    }
    
    func doSomething () {
        // setp 1
        self.getSumOf (array: [16.756.442,6,23]) {[zwak zelf] (som) in
            druk (sum)
            // stap 4, de uitvoering voltooien
        }
    }
// Hier slaan we de sluiting op voor toekomstig gebruik.
// Het zal de som van alle doorgegeven nummers afdrukken.

Voorbeeld 2 (asynchrone uitvoering):

func getSumOf (array: [Int], handler: @escaping ((Int) -> Void)) {
        //stap 2
        var sum: Int = 0
        voor waarde in array {
            som + = waarde
        }
        //stap 3
        Globals.delay (0.3, sluiting: {
            handler (sum)
        })
    }
    
    func doSomething () {
        // setp 1
        self.getSumOf (array: [16.756.442,6,23]) {[zwak zelf] (som) in
            druk (sum)
            // stap 4, de uitvoering voltooien
        }
    }
// Hier noemen we de sluiting met een vertraging van 0,3 seconden
// Het zal de som van alle doorgegeven nummers afdrukken.

Hier zijn we met de betekenis van het attribuut @escaping. Als u dus wilt ontsnappen aan de uitvoering van de afsluiting, gebruikt u het attribuut @escaping in Swift 3. De hierboven weergegeven fout van de compiler verdwijnt na het sluiten als ontsnappen met het attribuut @escaping.

Waarom hebben ze standaard @nonescaping gemaakt?

Standaard zijn er veel verschillende voordelen van het maken van niet-ontsnappen. De belangrijkste voordelen zijn prestaties en code-optimalisatie door de compiler, want als de compiler weet dat de sluiting niet-escaping is, zal hij zorgen voor de geheugentoewijzing voor de sluiting.

En een andere is, we kunnen zelf zonder problemen gebruiken bij niet-ontsnappende sluitingen omdat de sluiting wordt uitgevoerd voordat de functie terugkeert, zodat het zelf er zeker zal zijn. We hoeven geen zwakke zelf te gebruiken, dit is de extra functie ervan .

In Swift 3 zijn sluitingen standaard niet-escaping, kunnen @escaping worden gebruikt als dit niet is wat we willen. Niet-ontsnappende sluiting zal uitdagend worden uitgevoerd voordat de functie terugkeert.
Denk er altijd aan om zwak zelf te gebruiken tijdens het gebruik van een sluiting.

Bedankt voor het lezen, klik op het pictogram aanbevelen als je deze verzameling leuk vindt . Vragen? Laat ze achter in de reactie.