Подтвердить что ты не робот

Как протестировать протокол для метода?

Перед iOS 4 я использовал добавление наблюдателя к каждому MKAnnotationView, добавленному в представление карты, прислушиваясь к выбранному ему методу, поэтому я знаю, когда пользователь нажал на контакт.

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

Итак, я полагаю, что могу использовать метод -mapview:didSelectAnnotationView: из MKMapViewDelegate для моих нужд, но это было добавлено только в iOS 4.0 SDK.

Итак, чтобы поддерживать совместимость, я хотел бы реализовать этот метод у своего делегата и условно проверить наличие этого метода в протоколе MKMapViewDelegate, чтобы, если он не присутствует, я добавлю своего наблюдателя в аннотацию вид.

Как это сделать для метода протокола, аналогично тому, как мы проверяем, не класс ли nil?

UPDATE

Как отметил Даниэль Дикисон, я не могу использовать respondsToSelector:, потому что мой делегат имеет -mapview:didSelectAnnotationView: для 4.0+ устройств. Мне нужно проверить, имеет ли протокол на этом устройстве опционный метод -mapview:didSelectAnnotationView: ИЛИ, если MKMapView будет искать этот метод для делегирования.

Я закончил тест для текущей версии iOS. Если он выше 4.0, MKMapView будет искать этот метод и вызывать его.

if ([[[UIDevice currentDevice] systemVersion] doubleValue] < 4.0)
    [self setupObserver];

Это решает исходную проблему, но все равно будет интересно проверить фактический протокол для метода как-то.

4b9b3361

Ответ 1

Это сложная штука. Поэтому, если я правильно понимаю ваш вопрос, вы хотите узнать во время выполнения, отображает ли представление карты сообщение mapView:didSelectAnnotationView: его делегату. Но вы не можете использовать conformsToProtocol: или respondsToSelector:, потому что вы реализуете делегат, поэтому, очевидно, вы принимаете протокол и реализуете этот метод.

Единственное, о чем я могу думать, это проверить какой-либо другой метод, который был добавлен в MKMapView (а не делегат) в iOS 4, например: mapRectThatFits:.

Другая возможность заключается в использовании Objective-C библиотеки времени выполнения для запроса объекта протокола. Но это, вероятно, слишком много, и я не думаю, что это сработает, потому что Объект протокола создается компилятором при создании вашего приложения, и возможно, вы получите UIKit SDK-определенный объект протокола MKMapViewDelegate вместо того, чтобы скомпилировалось время выполнения.

Ответ 2

Поскольку нет экземпляра объекта, вы можете спросить, отвечает ли он на селектор сообщений, и вы уже знаете, что протокол поддерживается, но вы просто ищете один метод внутри - вам нужно использовать protocol_getMethodDescription, например (метод является экземпляром класса и необязательным), где вы проверяете нулевое возвращаемое значение:

#import <objc/runtime.h>

struct objc_method_description hasMethod = protocol_getMethodDescription(@protocol(MKMapViewDelegate), @selector(mapView:didSelectAnnotationView:), NO, YES);

if ( hasMethod.name != NULL )
{
...
}

Ответ 4

Я бы использовал метод respondsToSelector:, потому что это позволяет вам проверять определенные методы (что похоже на то, что вы делаете, в противном случае, если вы хотите проверить конкретный протокол, @Eric ответ хороший один). Этот SO post говорит об использовании этого способа.

В принципе, способ, которым вы его используете, -

SEL methodName = @selector(mymethod:);
BOOL test = [object respondsToSelector:methodName];

Ответ 5

Я сделал несколько иной подход.

Я просто использую #ifdef (__iPHONE_OS_VERSION_MIN_REQUIRED... и при необходимости добавляю наблюдателя, а также используя метод делегата -mapview:didSelectAnnotationView:.