J'ai mis à jour mon code vers Xcode 8.0 beta 6, mais je suis resté coincé avec ce qui semble être à propos du nouveau défaut de fermeture qui ne s'échappe pas. Dans le code suivant, Xcode suggère d'ajouter @escaping
devant completion:
sur la première ligne du code ci-dessous, mais cela ne compilera toujours pas et tournera en rond. *
(EDIT: En fait, @escaping devrait être ajouté dans aftercompletion:
, comme le suggère Xcode. L'alerte peut toujours s'afficher, mais le nettoyage et la compilation supprimeront it.) * Comment ce code devrait-il être réécrit/corrigé pour fonctionner dans le Swiftmis à jour 3? J'ai jeté un coup d'œil dans le nouveau manuel, mais je n'ai pas trouvé d'échantillons de code appropriés.
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 très appréciée!
Avant Swift 3, les attributs de fermeture @autoclosure
et @noescape
étaient des attributs du paramètre de fermeture , mais sont maintenant des attributs. au paramètre type ; voir la proposition d'évolution acceptée Swift suivante:
Votre question spécifique concerne l'attribut de type de paramètre @escaping
(auquel s'applique la même nouvelle règle), comme décrit dans la proposition acceptée Swift evolution pour laisser les paramètres de fermeture ne pas échapper par défaut:
Ces propositions sont désormais toutes deux implémentées dans la phase bêta de Xcode 8 (voir notes de version de Xcode 8 bêta 6 ; identifiant du compte dev. Nécessaire pour accéder).
Nouveauté de Xcode 8 beta 6 - Swift Compilateur: Swift Langue
Les paramètres de fermeture n'échappent pas par défaut, plutôt que d'être explicitement annotés avec
@noescape
. Utilisez@escaping
pour indiquer qu’un paramètre de fermeture peut s’échapper.@autoclosure(escaping)
est maintenant écrit en tant que@autoclosure @escaping
. Les annotations@noescape
et@autoclosure(escaping)
sont obsolètes. (SE-0103)...
Nouveauté de Xcode 8 beta - Swift et Apple Compilateurs LLVM: Swift Langue
Les attributs
@noescape
et@autoclosure
doivent maintenant être écrits avant le type de paramètre et non avant le nom du paramètre. [SE-0049]
Par conséquent, vous utilisez l'attribut @escaping
autre que par défaut comme suit; appliqué au type du paramètre de fermeture plutôt qu'au paramètre lui-même
func doSomething(withParameter parameter: Int, completion: @escaping () -> ()) {
// ...
}
(y compris ma réponse à une question dans un commentaire voté ci-dessous, car les commentaires ne sont pas des données persistantes sous SO)
@Cristi Băluță: "Que fait l'échappement? Jamais vu ces mots-clés avant la conversion automatique de Swift3 ..."
Voir par exemple le lien vers le proposition d'évolution SE-0103 ci-dessus (ainsi que le texte cité des notes de version beta 6): auparavant, les paramètres de fermeture s'échappaient par défaut (il n'était donc pas nécessaire de l'existence d'un lien explicite). annotation pour échapper), mais sont maintenant à la place non échappées, par défaut. D'où l'ajout de @escaping
pour annoter explicitement le fait qu'un paramètre de fermeture peut s'échapper (contrairement à son comportement par défaut). Cela explique également pourquoi @noescape
est maintenant obsolète (inutile d'annoter le comportement par défaut).
Pour expliquer ce que cela signifie qu'un paramètre de fermeture s'échappe, je cite le Référence du langage - attributs :
"Appliquez cet attribut au type de paramètre dans une déclaration de méthode ou de fonction pour indiquer que la valeur du paramètre peut être stockée pour une exécution ultérieure. Cela signifie que la valeur est autorisée à dépasser la durée de vie de l'appel."
@noescape
_De xcode 8 beta 6 @noescape
est la valeur par défaut. Auparavant, @escaping
était la valeur par défaut. Toute personne effectuant une mise à jour vers Swift 3.0 à partir de versions précédentes peut être confrontée à cette erreur.
Vous ne pouvez pas stocker une fermeture _@noescape
_ dans une variable. Parce que si vous pouvez stocker une fermeture dans une variable, vous pouvez exécuter la fermeture à partir de n’importe où dans votre code. Mais _@noescape
_ indique que le paramètre de fermeture ne peut pas échapper au corps de la fonction.
Cela donnera une 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 va compiler ok (écrire explicitement _@escaping
_)
_class MyClass {
var myClosure: (() -> ())?
func doSomething(finishBlock: @escaping () -> ()) {
myClosure = finishBlock
}
}
_
Avantages de _@noescape
_:
Pour plus de détails, consultez: Par défaut, les fermetures n'échappant pas