Ich habe mein (macOS) -Projekt in Xcode 8 nach Swift 3 konvertiert und erhalte die folgenden Warnungen mit mehreren Delegat-Methoden, die ich in Swift-Klassen implementiere:
Instance method 'someMethod' nearly matches optional requirement of protocol 'protocolName'
Ich bekomme dies für mehrere NSApplicationDelegate-Methoden wie applicationDidFinishLaunching
und applicationDidBecomeActive
:
Aber auch für Implementierungen von tableViewSelectionDidChange
:
Ich habe die Code-Vervollständigung verwendet, um die Methodensignaturen einzufügen, und versuchte auch, sie aus den SDK-Headern zu kopieren, um Tippfehler auszuschließen. Die Warnungen verschwinden einfach nicht und die Methoden werden nie aufgerufen.
Was fehlt mir hier?
Wir haben uns mit diesem Problem an den technischen Support von Apple Developer (DTS) gewandt .. __ Sie antworteten, dass dies ein Fehler in XCode 8 sei.
Wir haben einen Fehlerbericht eingereicht und hoffen auf ein schnelles Update. (Apple-Fehlerbericht-ID: 28315920).
Wenn Sie ein ähnliches Problem haben, geben Sie bitte auch Datei einen Fehlerbericht (bezogen auf unseren) an, damit die Apple-Ingenieure keinen einzigen Fall sehen.
Update für XCode ≥ 8.1
Das Problem scheint jetzt behoben zu sein, zumindest für die Delegat-Methoden, die wir in unserem Projekt verwenden.
Nach stundenlangem Suchen fand ich diese - Swift 3 ObjC Optionale Protokollmethode, die nicht in der Unterklasse aufgerufen wird
Sie können den Fehler umgehen, indem Sie die Funktion-c-Deklaration der Funktion voranstellen
@objc(tableViewSettingsDidChange:notification:)
func tableViewSettingsDidChange(_ notification:Notification)
Eine weitere Ursache für diese Warnung, wenn NSError
mit Swift verbunden wird:
In Anbetracht dieser Objective-C-Delegatmethode:
- (void)myService:(id<MYService>)myService didFailForSomeReason:(NSError *)error;
Das generiert automatisch diese Swift-Methode:
public func myService(_ myService: MYService!, didFailForSomeReason error: Error!)
Die Warnung wurde angezeigt.
In meinem Fall bestand der Grund darin, dass meine Klasse einen eigenen Error
-Typ hatte, so dass die Signatur in MyClass.Error
statt Swift.Error
aufgelöst wurde. Die Lösung bestand darin, den Parameter Error vollständig in Swift.Error
einzugeben:
public func myService(_ myService: MYService!, didFailForSomeReason error: Swift.Error!)
Ein Grund, warum Sie diesen Fehler erhalten könnten, betrifft Modifizierer für den Methodenzugriff. Zum Beispiel, wenn Sie die Funktion nicht als öffentlich definiert haben. Also für Methoden im CLLocationManagerDelegate-Fall:
func locationManager(_ manager: CLLocationManager,
didChangeAuthorization status: CLAuthorizationStatus)
zu:
public func locationManager(_ manager: CLLocationManager,
didChangeAuthorization status: CLAuthorizationStatus)
(d. h. machen Sie die Methode öffentlich) entfernt die Warnung und die Methode wird wie erwartet aufgerufen. Beachten Sie, dass bei der automatischen Vervollständigung der öffentliche Zugriffsmodifikator nicht für die Methode verwendet wird.
Für das Protokoll hatte ich das gleiche Problem bei der Implementierung der Delegated-Methode didFailProvisionalNavigation von WKWebView. Die Lösung bestand darin, die @objc-Deklaration und hinzuzufügen und den Typ des letzten Parameters von Error in NSError zu ändern:
@objc(webView:didFailProvisionalNavigation:withError:)
func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: NSError) {
// handle error
}
Hier ist was für mich behoben.
Ich habe die gleiche Warnung in einem Code erhalten, bei der ich sicher war, dass ich anfangs in den Editor eingegeben und die automatische Vervollständigung zugelassen habe. Anschließend ging ich zurück, um die Warnung erneut aufzurufen, und versuchte, die gleiche Funktion direkt nach meiner bestehenden Funktion erneut einzugeben. Als ich den Funktionsnamen erneut eingab, änderte sich meine Funktionssignatur, und die Parameter stimmten genau mit dem überein, was Xcode erwartete, und die Warnung wurde unterdrückt.
Wenn Sie also eine schnelle Überprüfung des Gesundheitszustandes durchführen möchten, tun Sie sich selbst einen Gefallen und geben Sie die Funktion noch einmal ein. Prüfen Sie, ob sich die Parm-Typen ändern. Das könnte alles sein, was Sie brauchen.
Um dies etwas zu kompliziert zu klären, muss man nur ein wenig komplizierte Problemumgehung hinzufügen: Kann jemand sehen, warum das Folgende nicht abläuft, wenn die Aktion ausgeführt wird?
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
}
}
}