172 votes

Paramètre de fermeture d'échappement optionnel Swift 3

Donné:

 typealias Action = () -> ()

var action: Action = { }

func doStuff(stuff: String, completion: @escaping Action) {
    print(stuff)
    action = completion
    completion()
}

func doStuffAgain() {
    print("again")
    action()
}

doStuff(stuff: "do stuff") { 
    print("swift 3!")
}

doStuffAgain()
 

Existe-t-il un moyen de définir le paramètre completion (et action ) de type Action? conservant @escaping ?

Changer le type donne l'erreur suivante:

error: @escaping attribute only applies to function types

En supprimant l'attribut @escaping , le code est compilé et exécuté, mais ne semble pas être correct car la fermeture completion échappe à la portée de la fonction.

241voto

Dmitry Coolerov Points 116

de: swift-liste de diffusion des utilisateurs

Fondamentalement, @échapper est valable uniquement sur les fermetures en fonction du paramètre de position. Le noescape par défaut, la règle ne s'applique qu'à ces fermetures en fonction du paramètre de position, sinon ils y échappent. Agrégats, tels que des énumérations avec les valeurs associées (par exemple, en Option), les tuples, les structures, etc., si ils ont des fermetures, suivez les règles par défaut pour les fermetures qui ne sont pas en fonction du paramètre de position, c'est à dire de s'échapper.

Donc facultatif paramètre de la fonction est @échapper par défaut.
@noeascape s'appliquent uniquement à la fonction de paramètre par défaut.

132voto

Jans Points 5261

Il y a un SR-2552 rapports qu' @escaping est de ne pas reconnaître la fonction alias de type. c'est pourquoi le message d'erreur @escaping attribute only applies to function types. vous pouvez contourner ce problème en élargissant le type de fonction dans la signature de la fonction:

typealias Action = () -> ()

var action: Action? = { }

func doStuff(stuff: String, completion: (@escaping ()->())?) {
    print(stuff)
    action = completion
    completion?()
}

func doStuffAgain() {
    print("again")
    action?()
}

doStuff(stuff: "do stuff") {
    print("swift 3!")
}

doStuffAgain()

EDIT 1::

En réalité, j'étais sous xcode beta 8 version où le bug SR-2552 n'était pas encore résolue. la fixation de bug, a introduit un nouveau(celui que vous êtes en face) qui est toujours ouvert. voir SR-2444.

La solution de contournement @Michael Ilseman pointu comme une solution temporaire est de supprimer l' @escaping attribut facultatif type de fonction, que garder de la fonction échapper.

func doStuff(stuff: String, completion: Action?) {...}

EDIT 2::

Le SR-2444 a été fermé précisant explicitement que les fermetures d'usines dans les paramètres de positions ne sont pas s'échapper et ont besoin d'être marqués avec l' @escaping à les faire s'échapper, mais les paramètres facultatifs sont implicitement échapper, depuis ((Int)->())? est un des synonymes de l' Optional<(Int)->()>facultatif, les fermetures sont en échapper.

24voto

Freeman Man Points 191

Je rencontre un problème similaire et parce que mélanger @ échapper et non échapper est très déroutant, surtout si vous avez besoin de passer les fermetures. Je me retrouve avec des paramètres par défaut (ce qui me semble plus logique)

 func doStuff(stuff: String = "do stuff",
        completion: @escaping (_ some: String) -> Void = { _ in }) {
     completion(stuff)
}

doStuff(stuff: "bla") {
    stuff in
    print(stuff)
}

doStuff() {
    stuff in
    print(stuff)
}
 

18voto

Igor Points 7487

Je l'ai fait fonctionner dans Swift 3 sans aucun avertissement de cette façon:

 func doStuff(stuff: String, completion: (()->())? ) {
    print(stuff)
    action = completion
    completion?()
}
 

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