2009-10-05 2 views
2

메시지를 보낼 필요가있는 objective-C 클래스의 포인터가 있습니다. 포인터는 잠재적으로 무엇이든지 될 수 있으므로 보내기 전에 메시지에 응답 할 것인지 확인해야합니다.포인터가 NSObject인지 어떻게 알 수 있습니까?

int delegatePreparedForSelector(id delegate, SEL aSelector) { 
    if (delegate 
     && [delegate isKindOfClass:[NSObject class]] 
     && [delegate respondsToSelector:aSelector]) { 
     return YES; 
    } 
    return NO; 
} 

문제는 때때로 위임 포인터가 struct objc-object * 점이다와 내가 isKindOfClass 메시지를 보낼 때 나는 EXC_BAD_ACCESS 나쁜 액세스 오류 : 여기가 검사를 수행하는 사용하고 기능입니다.

위임자가 내 메시지에 응답할지 결정하기 위해 사용해야하는 테스트가 더 있습니까?

답변

5

전화하기 전에 위임자가 처리되는 것처럼 들리지만이 코드에는 반드시 잘못된 것이 없습니다.

또한 베어 메어 ID를 사용하는 대신 id<MyDelegateProtocol> delegate과 같이 매개 변수에 프로토콜 구현을 적용 할 수 있습니다.

+0

이것이 문제입니다. 델리게이트가 할당 해제되고'nil'으로 설정되면, 타입이 struct objc_object *'로 설정됩니다. 이것은 디버거에서 보았습니다. – kubi

+0

위임자가 nil 인 경우 위의 내용은 충돌하지 않습니다. – bbum

+1

nil은 할당 해제 된 것과 다릅니다. – slf

-1

대리인 포인터가 가리키는의 Obj-C의 모든 객체 타입이기 때문에 (AN OBJ-C 객체 파고) 문제가 혼란을 일으키는 구조체 objc_object를 입력하기 :

struct objc_object 
{ 
    struct objc_class *isa; 
    /* extra stuff */ 
}; 

* 표시 ISA 포인트에 수업 .. 어떤 수업. 따라서 위임자로 설정하려는 객체가 존재하지 않거나 나쁜 메모리를 가리킬 수 있습니다.

+0

@try를 사용하여 신호 ('EXC_BAD_ACCESS')를 잡을 수 없습니다. –

+0

woops. 네가 옳아. 그러면 그는 그것을 밖으로 내야하고 버그가 무엇이든간에 추적해야합니다. – pxl

6

잠깐, 정말로 포인터가 아무것도 될 수 있다는 것을 의미합니까? 처럼 원시 malloc'ed 메모리 또는 NSObject에서 파생되지 않는 objc_object를 가리키고 있습니까? 이것이 사실이라면이 작업을 안전하게 할 수있는 방법이 없습니다. "이 포인터를 역 참조하지 않고 어떻게 역 참조를하는 것이 안전하다는 것을 알 수 있습니까?"라고하는 것과 같습니다. 유일한 방법은 그것을 전달한 것이 나쁜 포인터를 건네주지 않았다는 선험적 인 지식을 갖는 것입니다.

일부 신호 처리기 코드를 작성하여 EXEC_BAD_ACCESS를 정리할 수는 있지만 궁극적으로 천천히, 제대로 작동하지 않으며 다른 많은 실제 버그를 숨길 수 있습니다. 현실적으로 당신은 당신이 전달되는 것에 대해 약간의 제약이 있거나, 프로젝트의이 부분을 다시 설계해야합니다.