Предупреждение 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)
(т.е. сделать метод общедоступным) избавляется от предупреждения, и метод вызывается, как и ожидалось. Обратите внимание, что автозаполнение не помещает в метод модификатор открытого доступа.
Для меня проблема была нестандартной Error
class
В основном у меня был собственный класс с именем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