web-dev-qa-db-fra.com

Avertissement Xcode 8 "La méthode d'instance correspond presque à l'exigence facultative"

J'ai converti mon projet (macOS) en Swift 3 dans Xcode 8 et j'obtiens les avertissements suivants avec plusieurs méthodes de délégation que j'implémente dans les classes Swift:

Instance method 'someMethod' nearly matches optional requirement of protocol 'protocolName'

Je reçois ceci pour plusieurs méthodes NSApplicationDelegate telles que applicationDidFinishLaunching et applicationDidBecomeActive:

 enter image description here

Mais aussi pour les implémentations de tableViewSelectionDidChange:  enter image description here

 enter image description here

J'ai utilisé la complétion de code pour insérer les signatures de méthode et j'ai également essayé de les copier à partir des en-têtes du SDK pour éliminer les fautes de frappe. Les avertissements ne disparaissent pas et les méthodes ne sont jamais appelées. 

Qu'est-ce que j'oublie ici?

25
codingFriend1

Nous avons contacté le support technique des développeurs Apple (DTS) à ce sujet ..__ Ils nous ont répondu qu'il s'agissait d'un bug dans XCode 8.

Nous avons soumis un rapport de bogue et espérons une mise à jour rapide. (ID de rapport de bogue Apple: 28315920).

Si vous rencontrez un problème similaire, veuillez également déposer un rapport de bogue (en référence au nôtre) afin que les ingénieurs d'Apple voient qu'il ne s'agit pas d'un cas unique. 


Mise à jour pour XCode ≥ 8.1

Le problème semble résolu maintenant, du moins pour les méthodes de délégation que nous utilisons dans notre projet.

25
codingFriend1

Après des heures de recherche, j'ai trouvé ceci - Swift 3 ObjC Méthode de protocole facultative non appelée dans la sous-classe

Vous pouvez contourner le bogue en préfixant la déclaration objective-c sur la fonction

@objc(tableViewSettingsDidChange:notification:)
func tableViewSettingsDidChange(_ notification:Notification)
15
MickCrozier

Une autre cause de cet avertissement lorsque NSError est en cours de transition vers Swift:

Étant donné cette méthode de délégation Objective-C:

- (void)myService:(id<MYService>)myService didFailForSomeReason:(NSError *)error;

Cela génère automatiquement cette méthode Swift:

public func myService(_ myService: MYService!, didFailForSomeReason error: Error!)

L'avertissement a été montré.

Dans mon cas, la raison en était que ma classe avait son propre type Error et que la signature était résolue en MyClass.Error plutôt que Swift.Error. La solution consistait à saisir complètement le paramètre Error en le remplaçant par Swift.Error:

public func myService(_ myService: MYService!, didFailForSomeReason error: Swift.Error!)
4
Rory O'Bryan

Une des raisons pour lesquelles vous pourriez avoir cette erreur est liée aux modificateurs d'accès aux méthodes. Par exemple, si vous n'avez pas défini la fonction comme publique. Donc, pour les méthodes sur le cas CLLocationManagerDelegate, changer:

func locationManager(_ manager: CLLocationManager,
                     didChangeAuthorization status: CLAuthorizationStatus)

à:

public func locationManager(_ manager: CLLocationManager,
                            didChangeAuthorization status: CLAuthorizationStatus)

(c’est-à-dire rendre la méthode publique) supprime l’avertissement et la méthode est appelée comme prévu. Notez que la saisie semi-automatique ne met pas le modificateur d'accès public sur la méthode.

3
DCDC

Pour mémoire, j'ai eu le même problème lors de l'implémentation de la méthode déléguée didFailProvisionalNavigation de WKWebView. La solution consistait à ajouter la déclaration @objc et changer le type du dernier paramètre de Error à NSError:

@objc(webView:didFailProvisionalNavigation:withError:)
func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: NSError) {
    // handle error
}
1
pipacs

Voici ce qui l'a résolu pour moi.

J'obtenais le même avertissement dans un code que j'étais sûr d'avoir saisi initialement dans l'éditeur et de lui permettre de le compléter automatiquement. Par la suite, je suis retourné dans l'avertissement et j'ai essayé de saisir à nouveau la même fonction juste après ma fonction existante. Lorsque j'ai saisi à nouveau le nom de la fonction, la signature de ma fonction a changé et les paramétrages correspondaient exactement aux attentes de Xcode et l'avertissement a été supprimé.

Donc, si vous voulez faire une vérification de santé mentale rapide, faites-vous une faveur et essayez de taper une nouvelle fois dans la fonction pour voir si les types de paramètres changent. C'est peut-être tout ce dont vous avez besoin. 

1
ericdrum

Juste pour clarifier cette solution de contournement plutôt compliquée: quelqu'un peut-il comprendre pourquoi la procédure ci-dessous ne déclenche pas/ne fonctionne pas lorsque l'action est prise?

extension AppDelegate: UNUserNotificationCenterDelegate {
    @objc(userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler:)
    func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
        print("RESPONSE FROM NOTIFICATION!")

        switch response.actionIdentifier {
        case "reply":
            print("Reply action received!")
        case "ignore":
            print("Ignore action received!")
        default: print("Error - Unknown action received!")
            break
        }
    }
}
0
Mark Barrett