75 votes

Mise à jour des fermetures vers Swift 3 - @escaping

J'ai mis à jour mon code pour Xcode 8.0 beta 6 mais je suis coincé avec ce qui semble être sur le non échapper fermeture par défaut. Dans le code suivant Xcode suggère d'ajouter @escaping face completion: dans la première ligne du code ci-dessous, mais cela ne compile pas et va dans les cercles. *

(EDIT: En fait, @échappement doit être ajoutée après l' completion:, comme Xcode suggère. L'alerte peut encore montrer, mais le nettoyage et la compilation de l'enlever.)* Comment ce code ré-écrit / fixe à travailler dans la nouvelle Swift 3? J'ai eu un coup d'oeil dans le manuel, mais je n'arrivais pas à trouver des exemples de code.

func doSomething(withParameter parameter: Int, completion: () -> ()) {
    // Does something

    callSomeOtherFunc(withCompletion: completion)
  }

// Calling the method and execute closure 
doSomething(withParameter: 2) {
  // do things in closure
}

Toute aide appréciée!

58voto

dfri Points 11222

Swift 3: fermeture attributs de paramètres sont maintenant appliquées pour le paramètre de type, et pas le paramètre lui-même

Avant Swift 3, de la fermeture des attributs @autoclosure et @noescape utilisé pour être des attributs de la fermeture de paramètre, mais sont maintenant des attributs pour le paramètre type; voir la suite accepté Swift évolution de la proposition:

Votre question concernent le type de paramètre d'attribut @escaping (pour lesquels la même la nouvelle règle s'applique), comme décrit dans la accepté Swift évolution de la proposition de laisser la fermeture des paramètres non échapper par défaut:

Ces propositions sont actuellement mis en œuvre dans la phase bêta de Xcode 8 (voir les notes de version de Xcode beta 8 6; dev. compte de connexion nécessaires à l'accès)

Nouveau dans Xcode beta 8 6 - Swift Compilateur: Swift Langue

Fermeture paramètres sont non-fuyant par défaut, plutôt que d'être explicitement être annotée avec l' @noescape. Utiliser @escaping à indiquer qu'un fermeture paramètre peut s'échapper. @autoclosure(escaping) est maintenant écrite comme @autoclosure @escaping. Les annotations @noescapeet @autoclosure(escaping) sont obsolètes. (SE-0103)

...

Nouveau dans Xcode beta 8 – Swift et Apple LLVM Compilateurs: Swift Langue

L' @noescape et @autoclosure attributs doivent maintenant être écrite avant le type de paramètre à la place de avant le nom du paramètre. [SE-0049]

Par conséquent, vous utilisez la non-valeur par défaut @escaping attribut comme suit; appliqué au type de la fermeture de paramètre, plutôt que le paramètre lui-même

func doSomething(withParameter parameter: Int, completion: @escaping () -> ()) {
    // ...
}

(Y compris ma réponse à une question dans un upvoted commentaire ci-dessous, que les commentaires ne sont pas de données persistantes sur)

@Cristi Băluță: "Ce qui fait échapper? Jamais vu ce mots-clés avant swift3 auto-conversion ... "

Voir, par exemple, le lien vers le SE-0103 de l'évolution de la proposition ci-dessus (ainsi que le texte cité de la beta 6 notes de version): auparavant, la fermeture des paramètres échapper par défaut (et donc aucun besoin de l'existence d'une volonté explicite d'annotation pour l'échappement), mais maintenant plutôt le non échapper, par défaut. D'où l'ajout d' @escaping d'annoter explicitement qu'une fermeture paramètre peut échapper (contrairement à son comportement par défaut). Cela explique aussi pourquoi, @noescape est maintenant obsolète (pas besoin d'annoter le comportement par défaut).

Pour expliquer ce qu'il signifie qu'une fermeture paramètre est de fuir, je cite la Langue de Référence - les attributs:

"Appliquer cet attribut à un paramètre de type dans une méthode ou une déclaration de fonction pour indiquer que la valeur du paramètre peut être stockée pour plus tard l'exécution. Cela signifie que la valeur est autorisé à survivre à l' durée de l'appel."

22voto

Warif Akhand Rishi Points 3407

@noescape

À partir de xcode beta 8 6 @noescape est la valeur par défaut. Avant cela, @escaping a la valeur par défaut. Quelqu'un de la mise à jour de swift 3.0 à partir de versions précédentes pourraient faire face à cette erreur.

Vous ne pouvez pas enregistrer de @noescape de fermeture à l'intérieur d'une variable. Parce que si vous pouvez stocker une fermeture à l'intérieur d'une variable, vous pouvez exécuter la fermeture de n'importe où dans votre code. Mais @noescape stipule que la fermeture de paramètre ne peut pas s'échapper du corps de la fonction.

Cela donnera d'erreur du compilateur dans Xcode 8

class MyClass {

    var myClosure: (() -> ())?

    func doSomething(finishBlock: () -> ()) {
        myClosure = finishBlock    // ‼️ Error: Assigning non-escaping parameter 'finishBlock' to an @escaping closure
    }
}

Cela permettra de compiler ok (écrire explicitement @escaping)

class MyClass {

    var myClosure: (() -> ())?

    func doSomething(finishBlock: @escaping () -> ()) {
        myClosure = finishBlock
    }
}

Avantages de l' @noescape:

  • Compilateur peut optimiser votre code pour de meilleures Performances
  • Compilateur peut prendre soin de la gestion de la mémoire
  • Il n'est pas nécessaire d'utiliser une référence faible à soi-même dans la fermeture


Pour plus de détails consultez: le non-fuyant fermetures par défaut

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X