Erreur du compilateur: la méthode avec le sélecteur Objective-C est en conflit avec la déclaration précédente avec le même sélecteur Objective-C

Je commence à apprendre Swift, et j’ai suivi les très bonnes conférences vidéo de l’Université Stanford sur YouTube. Voici un lien si vous êtes intéressé ou ça aide (bien que ce ne soit pas nécessaire pour comprendre mon problème):

Développement d’applications iOS 8 avec Swift – 2. Plus Xcode et Swift, MVC

Tout en suivant les cours, je suis arrivé à un point où (autant que je puisse dire) mon code était identique au code de la vidéo mais sur mon système, j’ai eu une erreur de compilation. Après beaucoup d’essais et d’erreurs, j’ai réussi à réduire mon code à deux exemples, l’un générant une erreur, l’autre ou non, mais je n’ai aucune idée de la cause de l’erreur ou de sa résolution.

Le code qui crée l’erreur est le suivant:

import UIKit class BugViewController: UIViewController { func perform(operation: (Double) -> Double) { } func perform(operation: (Double, Double) -> Double) { } } 

Cela crée l’erreur de compilation suivante:

La méthode ‘performer’ avec le sélecteur Objective-C ‘effectue:’ est en conflit avec la déclaration précédente avec le même sélecteur Objective-C

En supprimant simplement la sous-classe de UIViewController, le code comstack:

 import UIKit class BugViewController { func perform(operation: (Double) -> Double) { } func perform(operation: (Double, Double) -> Double) { } } 

Quelques autres informations pouvant ou non être pertinentes:

  • Je suis récemment passé à Yosemite.
  • Lorsque j’ai installé Xcode, je me suis retrouvé avec une version bêta (version 6.3 (6D543q)) car (si je me souviens bien) c’était la version que je devais exécuter sur ma version d’OS X.

J’espère à moitié que c’est un bogue dans le compilateur car sinon cela n’a aucun sens pour moi. Toute aide reçue avec reconnaissance!

Objective-C ne prend pas en charge la surcharge de méthode, vous devez utiliser un nom de méthode différent. Lorsque vous avez hérité de UIViewController, vous avez hérité de NSObject et rendu la classe interopérable avec Obj-C. Swift, en revanche, prend en charge la surcharge, c’est pourquoi cela fonctionne lorsque vous supprimez l’inheritance.

Je suis moi-même en train de suivre le cours de Standford et je suis resté bloqué pendant longtemps aussi, mais après quelques recherches, j’ai trouvé quelque chose ici: les notes de version de Xcode et il a mentionné quelque chose ci-dessous:

Swift 1.2 est ssortingct sur la vérification de la surcharge basée sur les types de méthodes et d’initialiseurs @objc, ce qui n’est pas pris en charge par Objective-C.

 // Has the Objective-C selector "performOperation:". func performOperation(op: NSOperation) { /* do something */ } // Also has the selector "performOperation:". func performOperation(fn: () -> Void) { self.performOperation(NSBlockOperation(block: fn)) } 

Ce code fonctionnerait lorsqu’il est appelé depuis Swift, mais pourrait facilement se bloquer s’il est appelé depuis Objective-C. Pour résoudre ce problème, utilisez un type non pris en charge par Objective-C pour empêcher le compilateur Swift d’exposer le membre à l’environnement d’exécution Objective-C:

  • Si cela est logique, marquez le membre comme privé pour désactiver l’inférence de @objc.
  • Sinon, utilisez un paramètre factice avec une valeur par défaut, par exemple: _ nonobjc: () = (). (19826275)

Les substitutions de méthodes exposées à Objective-C dans des sous-classes privées ne sont pas supposées être @objc, ce qui provoque le blocage du compilateur Swift. Ajouter explicitement l’atsortingbut @objc à ces méthodes de substitution. (19935352)

Les symboles des kits de développement logiciel ne sont pas disponibles lors de l’utilisation de l’option Ouvrir rapidement dans un projet ou un espace de travail utilisant Swift. (20349540)

ce que je faisais était d’append simplement “private” devant la méthode override comme ceci:

  private func performOperation(operation: Double -> Double) { if operandStack.count >= 1 { displayValue = operation(operandStack.removeLast()) enter() } } 

Comme il a déjà été répondu, ObjC ne supporte pas la surcharge de méthodes (deux méthodes avec le même nom) et In swift 2 sous Xcode 7, il existe deux options pour résoudre ce type de problèmes. Une option consiste à renommer la méthode en utilisant l’atsortingbut: @objc(newNameMethod:)

 func methodOne(par1, par2) {...} @objc(methodTwo:) func methodOne(par1) {...} 

Une autre option pour résoudre ce problème dans Xcode 7+ consiste à appliquer l’atsortingbut @nonobjc à n’importe quelle méthode, indice ou initialiseur.

 func methodOne() {...} @nonobjc func methodOne() {...} 

Le problème est que UIViewController est une classe @objc . En héritant de UIViewController , BugViewController est également une classe @objc .

Cela signifie qu’il doit être conforme aux règles des sélecteurs Objective-C (le nom d’une méthode). Les méthodes func perform(operation: (Double) -> Double) et func perform(operation: (Double, Double) -> Double) deux ont le même sélecteur @selector(perform:) . Ceci n’est pas autorisé.

Pour résoudre ce problème, utilisez des noms différents: comme func perform1(operation: (Double) -> Double) et func perform2(operation: (Double, Double) -> Double) .


Je pense que la meilleure façon de gérer cela est de donner à vos méthodes perform() des noms plus descriptifs. Que font ces méthodes? Comment changent-ils l’état du contrôleur de vue? Examinez les autres méthodes UIViewController pour avoir une idée du style de nommage de la méthode ou lisez les noms de méthode qui doivent être expressifs et uniques dans une classe.

À partir de https://developer.apple.com/library/ios/releasenotes/DeveloperTools/RN-Xcode/Chapters/xc6_release_notes.html sous “Notes de version de Xcode 6.3” -> “Modifications rapides du langage”

Swift détecte maintenant les écarts entre la surcharge et le remplacement dans le système de type Swift et le comportement effectif observé via l’environnement d’exécution Objective-C.

J’ai eu la même erreur en ayant deux méthodes avec la même signature Obj-C:

 static func prepareForUpSyncing(obj : NSManagedObject!) -> Bool static func prepareForUpSyncing(objs : [NSManagedObject]!) -> Bool 

Je ne voulais pas marquer l’un d’eux comme @nonobjc en raison de la possibilité de conséquences imprévues à l’exécution. (Quelqu’un peut me corriger s’il n’y a pas de possibilité)

Il a été résolu en utilisant la fonctionnalité de nom de paramètre externe de Swift (dont le nom externe était le même que le nom local) pour la seconde méthode, qui modifie effectivement la signature de la méthode Obj-c:

 static func prepareForUpSyncing(objs objs : [NSManagedObject]!) -> Bool {