Iphone 如何测试方法的协议?

Iphone 如何测试方法的协议?,iphone,objective-c,cocoa,cocoa-touch,mapkit,Iphone,Objective C,Cocoa,Cocoa Touch,Mapkit,在iOS 4之前,我习惯于在地图视图中添加的每个MKAnnotationView中添加一个观察者,监听它所选择的方法,这样我就知道用户何时点击了pin 这在iOS 4.2之前运行良好。我注意到在发行版中,注释视图实际上被重用了,它不知怎么搞砸了观测者 因此,我想我可以使用MKMapViewDelegate中的-mapview:didSelectAnnotationView:方法来满足我的需要,但这只添加到iOS 4.0 SDK中 因此,为了保持兼容性,我想在我的委托上实现此方法,并有条件地检查M

在iOS 4之前,我习惯于在地图视图中添加的每个
MKAnnotationView
中添加一个观察者,监听它所选择的方法,这样我就知道用户何时点击了pin

这在iOS 4.2之前运行良好。我注意到在发行版中,注释视图实际上被重用了,它不知怎么搞砸了观测者

因此,我想我可以使用
MKMapViewDelegate
中的
-mapview:didSelectAnnotationView:
方法来满足我的需要,但这只添加到iOS 4.0 SDK中

因此,为了保持兼容性,我想在我的委托上实现此方法,并有条件地检查
MKMapViewDelegate
协议上是否存在此方法,以便如果它不存在,我会将我的观察者添加到注释视图中

对于协议方法,我如何做到这一点,类似于我们如何检查类是否为nil

更新

正如Daniel Dickison指出的,我不能使用响应选择器:,因为我的代理为4.0+设备实现了
-mapview:didSelectAnnotationView:
。我需要检查该设备上的协议是否具有可选的
-mapview:didSelectAnnotationView:
方法,或者
MKMapView
将在其委托上查找该方法

最后,我对当前运行的iOS版本进行了测试。如果它高于4.0,
MKMapView
将查找该方法并调用它

if ([[[UIDevice currentDevice] systemVersion] doubleValue] < 4.0)
    [self setupObserver];
if([[[UIDevice currentDevice]systemVersion]doubleValue]<4.0)
[自我观察者];
这解决了最初的问题,但以某种方式检查该方法的实际协议仍然很有趣。

我想您需要-类似于:

BOOL test = [myObject conformsToProtocol:@protocol(MKMapViewDelegate)];

我会使用
respondsToSelector:
方法,因为它允许您检查特定的方法(听起来像您正在这样做,否则,如果您要检查特定的协议,@Eric的答案是很好的)。这是关于以这种方式使用它的

基本上,你使用它的方式是

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

这是个棘手的问题。因此,如果我正确理解了您的问题,那么您希望在运行时了解map视图是否向其代理发送
mapView:didSelectAnnotationView:
消息。但是您不能使用
conformsToProtocol:
respondsToSelector:
,因为您正在实现委托,因此显然您正在采用协议并实现方法

我能想到的唯一一件事是检查在iOS 4中添加到
MKMapView
(不是委托)的其他方法,例如:
maprecthatthafits:


另一种可能是使用来查询协议对象。但这可能有些过分,而且我认为它不会起作用,因为当你构建你的应用程序时,你可能会得到UIKit SDK定义的
MKMapViewDelegate
protocol对象,而不是编译运行时使用的任何对象。

我采取了一种稍微不同的方法


我只是使用了一个
#ifdef(\uuuIphone\u OS\u VERSION\u MIN\u REQUIRED…
并在必要时添加观察者,同时使用
-mapview:didSelectAnnotationView:
委托方法。

因为没有对象实例,您可以询问它是否响应消息选择器,并且您已经知道该协议受支持,但您只是在-您需要使用
协议\u getMethodDescription
,就像这样(方法是类实例和可选的),在这里检查nil返回值:

#import <objc/runtime.h>

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

if ( hasMethod.name != NULL )
{
...
}
#导入
struct objc_method_description hasMethod=protocol_getMethodDescription(@protocol(MKMapViewDelegate),@selector(mapView:didSelectAnnotationView:),否,是);
if(hasMethod.name!=NULL)
{
...
}

Chris-您可能不想使用保留关键字select作为SEL变量名。@DHamrick,您完全正确……太愚蠢了……我写得很快,而且有一个掌心……您不能使用“respondsToSelector”因为您唯一需要询问的对象是您自己!您需要了解MKMapView是否会从委托中查找该方法…不一定,如果该对象正在实现一个协议,该协议可能包含该方法,也可能不包含该方法,您可能希望您的通用代码与委托实现的内容完全无关。您是没有任何意义。将实现委托方法的唯一对象是您编写的对象-没有系统MKMapView委托。这是您自己的控制器!您已经知道它实现了此方法。提问者想知道的是是否会调用此方法。您只能通过查看协议的内容来了解这一点ol包含,因为MKMapView将在您自己的代码上调用“respondsToSelector!”#ifdef(u iPHONE_OS_VERSION_MIN_REQUIRED)将在构建时解决,而不是在运行时解决,因此一旦构建应用程序,无论它运行在什么设备/操作系统上,它都将执行相同的操作。这不起作用。您需要在运行时而不是构建时了解设备的iOS版本。
\u iPHONE\u OS\u version\u MIN\u REQUIRED
将始终返回您在构建时指定的值设置,不管您在哪个设备/iOS版本上运行它。这是我采取的方法。您的要求可能不同。您发布的频率有多高?您的项目是一个移动目标吗?您的团队中有多少开发人员?同样,这只是我采取的方法(这可能会或可能不会激发您的更新)。该协议不应该被引用为
@protocol(MKMapViewDelegate)
?在任何情况下,我感觉这将使用SDK提供的MKMapViewDelegate,而不是运行时。您对@protocol的看法是正确的(我修复了代码)但由于检查是在运行时进行的,它将查看应用程序运行时存在的协议