2010-11-24 6 views
13

iOS 4 이전에는지도보기에 추가 된 각 MKAnnotationView에 옵저버를 추가하여 사용자가 핀을 탭한 시점을 알았습니다.메소드의 프로토콜을 테스트하는 방법은 무엇입니까?

iOS 4.2까지 정상적으로 작동합니다. 주목해야 할 사실은 주석 뷰는 실제로 재사용되고 있으며 관찰자와 어딘지를 망칠 수 있다는 점입니다.

따라서 메서드를 MKMapViewDelegate에서 사용할 수 있지만이 기능은 iOS 4.0 SDK에만 추가되었습니다.

호환성을 유지하기 위해 위임자에게이 메서드를 구현하고 MKMapViewDelegate 프로토콜에서이 메서드가 있는지 조건부로 확인하여 제시되지 않은 경우 해당 옵저버를 주석보기에 추가합니다. .

클래스가 nil이 아닌지 확인하는 방법과 마찬가지로 프로토콜 메소드에 대해이 작업을 수행 할 수 있습니까?

UPDATE : 다니엘 Dickison는 지적 내 대리인이 -mapview:didSelectAnnotationView:은 4.0 장치를 구현했기 때문에

, 내가 respondsToSelector:을 사용할 수 없습니다. 필요한 것은 해당 장치의 프로토콜에 -mapview:didSelectAnnotationView: 메서드 또는이 있는지 확인하는 것입니다. MKMapView이 위임자의 메서드를 찾으면 해당 프로토콜을 찾습니다.

현재 실행중인 iOS 버전에 대한 테스트를 마쳤습니다. 4.0보다 높으면 MKMapView이 해당 메소드를 찾아서 호출합니다.

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

원래 문제는 해결되었지만 실제 프로토콜을 어떻게 든 검사하는 것은 흥미로울 것입니다.

답변

5

입니다. 따라서 질문을 올바르게 이해하고 있다면 런타임에지도보기가 mapView:didSelectAnnotationView: 메시지를 대리인에게 전송하는지 여부를 알아야합니다. 그러나 conformsToProtocol: 또는 respondsToSelector:을 사용할 수 없습니다. 위임자를 구현 중이므로 프로토콜을 채택하고 메서드를 구현하고 있기 때문입니다.

제가 생각할 수있는 유일한 점은 mapRectThatFits:과 같이 iOS 4에서 MKMapView (대리인이 아님)에 추가 된 다른 방법을 확인하는 것입니다.

또 다른 가능성은 Objective-C runtime library을 사용하여 Protocol 개체를 쿼리하는 것입니다.하지만 이것은 아마도 과도한 일일 것입니다. 또한 앱을 빌드 할 때 Protocol object is created by the compiler이 있기 때문에 작동하지 않을 것입니다. UIKit SDK에 정의 된 MKMapViewDelegate 프로토콜 객체를 런타임에 컴파일하는 대신 가져올 수 있습니다.

2
즉 당신이하고있는 것처럼 들린다 (구체적인 방법을 확인 할 수 있기 때문에 내가 그렇지 않으면 respondsToSelector: 방법을 사용

, 당신이 ' 특정 프로토콜을 확인하기 위해 다시 찾고, @ 에릭의 대답은 좋은 것입니다). 이 SO post은 이런 식으로 사용하는 것에 대해 이야기합니다.

기본적으로, 당신이 그것을 사용하려는 방법은 까다로운 하나

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

Chris - SEL 변수 이름으로 예약 키워드 select를 사용하지 않을 수 있습니다. – DHamrick

+0

@DHamrick, 당신은 절대적으로 옳았습니다 ... 너무 바보 같았습니다 ... 나는 그것을 빨리 쓰고 얼굴 손바닥을 가지고있었습니다. –

+1

"respondsToSelector"는 물을 것입니다. MKMapView가 위임자로부터 해당 메서드를 찾고 있는지 알아야합니다. –

0

약간 다른 접근 방식을 취했습니다.

단순히 #ifdef (__iPHONE_OS_VERSION_MIN_REQUIRED...을 사용하고 필요에 따라 옵저버를 추가하고 -mapview:didSelectAnnotationView: 대리자 메서드를 사용합니다.

+0

"#ifdef (__iPHONE_OS_VERSION_MIN_REQUIRED")는 런타임이 아닌 빌드시 해결되므로 일단 앱을 빌드하면 실행중인 장치/OS와 상관없이 항상 동일한 작업을 수행합니다. –

+0

예, 간단히 설명했습니다. 그가 말한 문제 – joshpaul

+0

이것은 작동하지 않습니다. 빌드 할 때 런타임이 아닌 런타임에 Device의 iOS 버전을 알아야합니다. '__iPHONE_OS_VERSION_MIN_REQUIRED'는 빌드 설정에서 지정한 값을 항상 반환합니다. Device/iOS 버전을 사용하고 있습니다. – leolobato

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) 
{ 
... 
} 
+0

프로토콜은'@protocol (MKMapViewDelegate) '로 참조되지 않아야합니까? 런타임은 SDK가 제공하는 MKMapViewDelegate를 사용합니다. –

+0

당신은 @protocol (코드를 수정했습니다)에 대해 옳았습니다.하지만 검사는 런타임이므로 응용 프로그램이 실행될 때 존재하는 프로토콜을 볼 것입니다. 아마 또한 MKMapKit 프레임 워크는 약 링크되어야합니다 (앱 타겟에서는 "정보 입수"를하고 일반 탭에서는 프레임 워크 목록을 살펴보고 MapKit을 "필수"에서 "약한"으로 변경). –

+0

이 문서의 "프로토콜 객체"섹션의 마지막 두 단락을 확인하십시오. 런타임 대신 SDK가 정의한대로 프로토콜을 얻을 수 있음을 의미한다고 생각합니다. http://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/ObjectiveC/Articles/ocProtocols.html#//apple_ref/doc/uid/TP30001163-CH15-TPXREF149 –

관련 문제