Предупреждение Xcode 8 "Метод экземпляра почти соответствует необязательному требованию"

Я преобразовал свой (macOS) проект в Swift 3 в Xcode 8 и получаю следующие предупреждения с несколькими методами делегатов, которые я реализую в классах swift:

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

Я получаю это для нескольких методов NSApplicationDelegate, таких как applicationDidFinishLaunching а также applicationDidBecomeActive:

Но и для реализации tableViewSelectionDidChange:

Я использовал завершение кода, чтобы вставить сигнатуры методов, а также попытался скопировать их из заголовков SDK, чтобы исключить опечатки. Предупреждения просто не исчезают, а методы никогда не вызываются.

Что мне здесь не хватает?

7 ответов

Решение

Мы связались с технической поддержкой Apple для разработчиков по этой проблеме. Они ответили, что это ошибка в XCode 8.

Мы отправили сообщение об ошибке и надеемся на быстрое обновление. (Apple Bug Report ID: 28315920).

Если у вас возникла похожая проблема, пожалуйста, также сообщите об ошибке (ссылаясь на нашу), чтобы инженеры Apple увидели ее не один случай.


Обновление для XCode ≥ 8.1

Кажется, проблема решена, по крайней мере, для методов делегатов, которые мы используем в нашем проекте.

После нескольких часов поиска я нашел это - необязательный метод протокола Swift 3 ObjC, не вызываемый в подклассе

Вы можете обойти ошибку, добавив префикс Objective-C в функции

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

Одна из причин, по которой вы можете получить эту ошибку, связана с модификаторами доступа к методу. Например, если вы не определили функцию как общедоступную. Так для методов в случае CLLocationManagerDelegate, изменив:

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

чтобы:

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

(т.е. сделать метод общедоступным) избавляется от предупреждения, и метод вызывается, как и ожидалось. Обратите внимание, что автозаполнение не помещает в метод модификатор открытого доступа.

Для меня проблема была нестандартной Errorclass
В основном у меня был собственный класс с именемError и компилятор рассматривал delegate method как местный метод

Я просто изменил имя своего собственного класса, и это сработало. Итак, просто подтвердите, что у вас нет такого же имени класса в функции

Еще одна причина этого предупреждения, когда NSError соединяется со Свифтом:

Учитывая этот метод делегата Objective C:

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

Это автоматически генерирует этот метод Swift:

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

Предупреждение было показано.

В моем случае причина была в том, что у моего класса были свои Error типа так подпись была разрешена MyClass.Error скорее, чем Swift.Error, Решение состояло в том, чтобы полностью ввести параметр Error, изменив его на Swift.Error:

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

Для записи, у меня была та же проблема при реализации метода делегата WKWebView didFailProvisionalNavigation. Решением было добавить объявление @objc и изменить тип последнего параметра с Error на NSError:

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

Вот что исправило это для меня.

В каком-то коде я получал такое же предупреждение, что был уверен, что изначально набрал в редакторе и разрешил автозаполнение. Впоследствии я вернулся и снова просмотрел предупреждение и попытался просто набрать ту же функцию снова сразу после моей существующей функции. Когда я снова ввел имя функции, моя сигнатура функции изменилась, и параметры точно соответствовали ожидаемому Xcode, и предупреждение было подавлено.

Поэтому, если вы хотите сделать быструю проверку работоспособности, сделайте себе одолжение и попробуйте еще раз ввести функцию и посмотреть, не изменятся ли типы параметров. Это может быть все, что вам нужно.

Это заставило меня ходить по кругу. Это произошло потому, что я создал свой собственный класс уведомлений. Как только я изменил имя этого класса (не реорганизуйте его, так как это изменит параметры уведомлений objc), все ошибки исчезли

Просто чтобы прояснить этот довольно сложный обходной путь: может кто-нибудь понять, почему нижеприведенное не срабатывает / не работает, когда выполняется действие?

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
        }
    }
}

Для xcode 8.1 >= и swift 3,

добавьте @nonobjc в начале метода, чтобы отключить это предупреждение.

Я обнаружил, что это предупреждение в основном из-за того, когда соответствуют протоколу UITableViewDelegate вместо UITableViewDataSource

Пожалуйста, проверьте, если вы пропали без вести UITableViewDataSource

Другие вопросы по тегам