Метод не - '@ objc' не удовлетворяет необязательному требованию протокола '@objc' с условным расширением

Я пытаюсь создать реализацию MKMapViewDelegate по умолчанию, используя условное расширение следующим образом:

extension MKMapViewDelegate where Self: NSObject {
        func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
            ...
        }

        func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
            ...
        }
    }

Однако, когда я компилирую код, я получаю предупреждение

Не - '@ objc' метод 'mapView (_: viewFor :)' не удовлетворяет необязательному требованию протокола '@objc' MKMapViewDelegate '

Я ожидал, что соответствие «Я» NSObject будет означать, что предупреждение не появится. Помимо предупреждения, методы делегата не вызываются, даже если экземпляр делегата является UIViewController и, следовательно, соответствует NSObject.

Я неправильно понимаю, как «где» работает в расширениях?


person Mattias Bowallius    schedule 24.08.2016    source источник
comment
Возможный дубликат метода не - '@ objc' не удовлетворяет необязательному требованию протокола @objc   -  person Richard Venable    schedule 29.09.2016


Ответы (1)


NSObject больше не будет делать вывод о @objc в Swift 4 из-за принятия Предложение Дуга Грегора: SE-0160.

Я признаю, что не нашел времени, чтобы понять причину вашей ошибки. Я просто опубликовал этот ответ в надежде, что кто-нибудь, читающий ваш вопрос, увидит следующий совет.

Это плохая практика или «запах кода» - предоставлять реализацию протокола по умолчанию для всего модуля. Я бы порекомендовал альтернативный подход, в котором вы создаете настраиваемый тип, такой как MapViewDelegate, с некоторым поведением по умолчанию, которое может использоваться типами, которые явно соответствуют этому protocol.

Например:

import MapKit
protocol MapViewDelegate: MKMapViewDelegate {}
extension MapViewDelegate where Self: NSObject {
    func annotationView(for annotation: MKAnnotation, in mapView: MKMapView) -> MKAnnotationView? {
        …
    }

    func renderer(for overlay: MKOverlay, in mapView: MKMapView) -> MKOverlayRenderer {
        …
    }
}
final class MyMapDelegate: NSObject, MapViewDelegate {
    func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
        return annotationView(for: annotation, in: mapView)
    }
    func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
        return renderer(for: overlay, in: mapView)
    }
}
person Infinity James    schedule 20.05.2017
comment
Хотя это функциональное решение, оно на самом деле не дает ответа на вопрос. Вопрос заключался в том, почему соответствие NSObject не избавляет от предупреждений. - person Mattias Bowallius; 22.05.2017