web-dev-qa-db-fra.com

Xcode 8: les types de fonction ne peuvent pas avoir d'étiquette d'argument brisant ma construction

Il semble que, pour une raison quelconque, Swift ait choisi de rendre son codage moins lisible en obligeant les utilisateurs à supprimer les étiquettes de paramètre du gestionnaire d'achèvement. J'ai lu la discussion Swift et pense toujours que c'est une erreur. Au moins, ils auraient pu le rendre facultatif.

Lors de la construction avec Xcode 8 - existe-t-il un moyen de forcer le compilateur à utiliser Swift 2.3 afin que je ne reçois plus ces erreurs? J'ai mis à jour l'option d'utilisation de legacy Swift (sous les paramètres de construction) legacy support in xcode mais je semble toujours avoir cette erreur:

Les types de fonction ne peuvent pas avoir l'argument label 'isloggedIn'; utilisez '_' à la place

error Xcode 8

Comment puis-je conserver mes étiquettes dans mes gestionnaires d'achèvement?

71
UKDataGeek

Les concepteurs Swift) ont décidé d'interdire les étiquettes d'argument pour les types de fonction.

Le raisonnement est expliqué ici: https://github.com/Apple/Swift-evolution/blob/master/proposals/0111-remove-arg-label-type-significance.md

Ce choix est frustrant et discutable, car interdire les étiquettes d’arguments facilite beaucoup l’invocation incorrecte de fermetures, ce qui semble plus important que de simplifier le système de types de la langue.

Ergonomie> idéologie.

93
Crashalot

Une solution de contournement à considérer. Tu ne peux pas faire:

func doStuff(completion: (foo: Int, bar: String) -> Void) {
    ...
    completion(foo: 0, bar: "")
}

... mais vous pouvez faire:

func doStuff(completion: ((foo: Int, bar: String)) -> Void) {
    ...
    completion((foo: 0, bar: ""))
}

c'est-à-dire que vous avez un seul argument non nommé pour votre fermeture, qui est un tuple, dans ce cas (foo: Int, bar: String).

C'est moche à sa manière, mais au moins vous conservez les étiquettes d'argument.

Avertissement: je n'ai pas pensé aux implications de cette approche en termes de capture ou de performances.

21
sam-w

Sur la base des informations ci-dessus, il apparaît que le seul moyen de résoudre ce problème et de s’assurer que ses performances sont optimales consiste à formuler une proposition visant à rendre les étiquettes d’argument facultatives afin de:

  1. l'amélioration de la vitesse de développement (sans étiquettes d'arguments, cela nous oblige à faire défiler la méthode jusqu'à la fin de la méthode à chaque fois que nous utilisons le gestionnaire d'achèvement.
  2. Réduire les erreurs: (j'ai déjà eu plusieurs erreurs en raison d'entrées de gestionnaire d'achèvement incorrectes, en particulier avec celles qui attendent des valeurs booléennes)
  3. Rendre le code plus lisible pour tous les membres de l'équipe. Tout le monde n'a pas qu'un seul membre de l'équipe et il est donc indispensable de pouvoir facilement récupérer le code des autres peuples.
  4. Enfin, une bonne pratique de programmation signifie que la solution doit ressembler autant à l’élément en cours de développement. completionhandler: (newvalues, nil) ressemble moins à l'élément géré que completionhandler(results: newValue, error:nil)

J'aimerais que les lecteurs lisent ceci pour partager leurs réactions/commentaires ci-dessous avant de le soumettre afin que je puisse montrer qu'il y en a d'autres qui le soutiennent.

Edit: J'ai soumis le pitch ici: https://lists.Swift.org/pipermail/Swift-evolution/Week- of-Mon-20161010/028083.html qui semble avoir été convenu. Il semble que cela va se produire, cependant la discussion est de savoir si ceci est soumis comme une amélioration Swift 4 (hautement probable)

10
UKDataGeek

Vous devez utiliser _ pour que vos paramètres ne soient pas nommés, ce qui est regrettable. Au lieu d'attacher _ à chaque paramètre puis d'appeler aveuglément votre fonction, je suggèrerais de créer un objet wrapper.

Puisque perdre des paramètres nommés pour des types de fonction introduit plus de risque que vous appeliez la fonction avec des valeurs incorrectes, je suggérerais de placer les paramètres dans une structure et d’avoir ce paramètre unique pour votre fonction.

De cette façon, les champs de votre structure sont nommés et il n’ya qu’un seul type de valeur à transmettre à votre fonction. C'est plus lourd que si nous pouvions nommer les paramètres de la fonction, mais nous ne pouvons pas. Au moins, vous serez plus en sécurité et vous vous sentirez moins sale.

struct LineNoteCellState {

    var lineNoteText: String?
    var printOnInvoice = false
    var printOnLabel = false
}

Voici un exemple d'utilisation:

cell.configure(editCallback: { (_ state: LineNoteCellState) in

    self.lineNoteText = state.lineNoteText
    self.printOnInvoice = state.printOnInvoice
    self.printOnLabel = state.printOnLabel
})
9
Michael Peterson

Solution partielle, notez le _

completion: (_ success: Bool) -> Void
4
Maciej Swic