Предупреждение Xcode 8 "Метод экземпляра почти соответствует необязательному требованию"
Я преобразовал свой (macOS) проект в Swift 3 в Xcode 8 и получаю следующие предупреждения с несколькими методами делегатов, которые я реализую в классах swift:
Instance method 'someMethod' nearly matches optional requirement of protocol 'protocolName'
Я получаю это для нескольких методов NSApplicationDelegate, таких как applicationDidFinishLaunching
и applicationDidBecomeActive
:
![enter image description here]()
Но также для реализаций tableViewSelectionDidChange
: ![enter image description here]()
![enter image description here]()
Я использовал завершение кода, чтобы вставить сигнатуры методов, а также попытался скопировать их из заголовков SDK, чтобы исключить опечатки. Предупреждения просто не исчезают, а методы никогда не вызываются.
Что мне здесь не хватает?
Ответы
Ответ 1
Мы связались с технической поддержкой Apple для разработчиков по этой проблеме. Они ответили, что это ошибка в Xcode 8.
Мы отправили отчет об ошибке и надеемся на быстрое обновление. (Apple Bug Report ID: 28315920).
Если у вас возникла похожая проблема, пожалуйста, также сообщите об ошибке (ссылаясь на нашу), чтобы инженеры Apple увидели ее не один случай.
Обновление для Xcode ≥ 8.1
Кажется, проблема исправлена, по крайней мере, для методов делегатов, которые мы используем в нашем проекте.
Ответ 2
После нескольких часов поиска я нашел это - Swift 3 ObjC Необязательный метод протокола, не вызываемый в подклассе
Вы можете обход ошибки, префикс объявления objective-c в функции
@objc(tableViewSettingsDidChange:notification:)
func tableViewSettingsDidChange(_ notification:Notification)
Ответ 3
Одна из причин, по которой вы можете получить эту ошибку, связана с модификаторами доступа к методу. Например, если вы не определили функцию как общедоступную. Таким образом, для методов в случае CLLocationManagerDelegate, изменив:
func locationManager(_ manager: CLLocationManager,
didChangeAuthorization status: CLAuthorizationStatus)
чтобы:
public func locationManager(_ manager: CLLocationManager,
didChangeAuthorization status: CLAuthorizationStatus)
(т.е. сделать метод общедоступным) избавляется от предупреждения, и метод вызывается, как и ожидалось. Обратите внимание, что автозаполнение не помещает в метод модификатор открытого доступа.
Ответ 4
Другая причина этого предупреждения, когда NSError
соединяется с Swift:
Учитывая этот метод делегата 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!)
Ответ 5
Для записи у меня была та же проблема при реализации метода делегата WKWebView didFailProvisionNavigation. Решением было добавить объявление @objc и изменить тип последнего параметра с "Ошибка на NSError":
@objc(webView:didFailProvisionalNavigation:withError:)
func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: NSError) {
// handle error
}
Ответ 6
Вот что исправил это для меня.
Я получал то же предупреждение в каком-то коде, что был уверен, что набрал вначале редактор и разрешил автозаполнение. Впоследствии я вернулся и повторил предупреждение и попытался просто набрать ту же функцию снова после моей существующей функции. Когда я снова ввел имя функции, моя сигнатура функции изменилась, и парфюмы точно совпали с ожидаемым ожиданием Xcode и предупреждением было подавлено.
Итак, если вы хотите сделать быструю проверку здравомыслия, сделайте себе одолжение и попробуйте ввести функцию еще раз и посмотрите, меняются типы парм. Это может быть все, что вам нужно.
Ответ 7
Просто добавьте разъяснения к этому довольно сложному обходному пути: может ли кто-нибудь понять, почему ниже не срабатывает/работает при выполнении действия?
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
}
}
}
Ответ 8
Для xcode 8.1 >= и быстрого 3,
добавить @nonobjc в начале метода, чтобы отключить это предупреждение.
Ответ 9
Я обнаружил, что это предупреждение в основном связано с тем, что соответствует протоколу UITableViewDelegate
вместо UITableViewDataSource
Пожалуйста, проверьте, не хватает ли вы UITableViewDataSource