在iOS 4之前,我曾经为添加到地图视图的每个MKAnnotationView
添加了一个观察者,听取了它的选择方法,所以我知道用户何时点击了一个图钉。
这适用于iOS 4.2。我注意到在发布时注意到注释视图实际上正在被重用,并且它在某种程度上与观察者混淆。
所以我认为我可以使用-mapview:didSelectAnnotationView:
中的MKMapViewDelegate
方法来满足我的需求,但这只是添加到iOS 4.0 SDK中。
因此,为了保持兼容性,我想在我的委托上实现此方法,并有条件地检查MKMapViewDelegate
协议上是否存在此方法,以便如果它不存在,我将添加我的观察者注释视图。
我如何为协议方法执行此操作,类似于我们如何检查类是否为零?
更新:
Daniel Dickison指出,我不能使用respondsToSelector:
,因为我的代表已为4.0+设备实施了-mapview:didSelectAnnotationView:
。我需要检查该设备上的协议是否具有可选的-mapview:didSelectAnnotationView:
方法 OR ,如果MKMapView
将在其代理上查找该方法。
我最终对当前运行的iOS版本进行了测试。如果它高于4.0,MKMapView
将查找该方法并调用它。
if ([[[UIDevice currentDevice] systemVersion] doubleValue] < 4.0)
[self setupObserver];
这解决了原始问题,但以某种方式检查方法的实际协议仍然很有趣。
答案 0 :(得分:26)
因为没有对象实例,您可以询问它是否响应消息选择器,并且您已经知道协议是受支持的,但您只是在寻找一种方法 - 您需要使用protocol_getMethodDescription
,如此(方法是类实例和可选),您检查nil返回值:
#import <objc/runtime.h>
struct objc_method_description hasMethod = protocol_getMethodDescription(@protocol(MKMapViewDelegate), @selector(mapView:didSelectAnnotationView:), NO, YES);
if ( hasMethod.name != NULL )
{
...
}
答案 1 :(得分:5)
这是一个棘手的问题。因此,如果我正确理解您的问题,您希望在运行时找出地图视图是否将mapView:didSelectAnnotationView:
消息发送给其委托。但是,您无法使用conformsToProtocol:
或respondsToSelector:
因为您正在实施代理,所以很明显您正在采用该协议并实施该方法。
我唯一能想到的是检查在iOS 4中添加到MKMapView
(而不是委托)的其他方法,例如:mapRectThatFits:
。
另一种可能性是使用Objective-C runtime library来查询Protocol对象。但这可能有些过分,而且我认为它不会起作用,因为Protocol object is created by the compiler在您构建应用时,您可能会获得UIKit SDK定义的{{0}} {1}}协议对象,而不是编译运行时的任何内容。
答案 2 :(得分:3)
我认为你想要NSObject conformsToProtocol - 类似于:
BOOL test = [myObject conformsToProtocol:@protocol(MKMapViewDelegate)];
答案 3 :(得分:2)
我会使用respondsToSelector:
方法因为这可以让你检查特定的方法(这听起来像你正在做的,否则,如果你想检查一个特定的协议,@ Eric的答案是一个好的)。这篇SO post讨论了如何以这种方式使用它。
基本上,你使用它的方式是
SEL methodName = @selector(mymethod:);
BOOL test = [object respondsToSelector:methodName];
答案 4 :(得分:0)
我采取了略微不同的方法。
我只需使用#ifdef (__iPHONE_OS_VERSION_MIN_REQUIRED...
并在必要时添加观察者,并使用-mapview:didSelectAnnotationView:
委托方法。