2012-12-10 9 views
5

프로젝트 내에 개발 단계에서 테스트 클래스가 있지만이 테스트 클래스는 앱 스토어 빌드 용으로 컴파일됩니다.조건부 호출에 NSClassFromString을 사용할 수있는 방법을 모르겠다.

내가 NSClassFromString 클래스는 예제 코드와 같은 존재하는지 확인하는 데 사용할 수있는 몇 권의 책에서 읽었습니다 :

if (NSClassFromString(@"SomeClass") != nil) 
{ 
[SomeClass someMethod]; 
} 
else 
{ 
code not using SomeClass 
} 

그러나 내 프로젝트에 연습으로이 퍼팅 후, 나는 '것을 발견 SomeClass를 포함하는 소스 파일을 제거한 대상에 대한 링크 오류가 발생했습니다.

그러므로 내 결론은 클래스의 존재 여부를 결정하는 메커니즘은 해당 클래스가 다른 클래스를 사용하는 라이브러리 또는 소스 파일 내에있는 경우에만 유용합니다 (이 문제를 언급 한 책에서 누락 된 세부 사항 기술). 또는 뭔가 빠졌습니까?

답변

6

NSClassFromString은 명명 된 클래스의 런타임을 검색합니다. 사실상 클래스가 존재하는지 여부를 결정합니다.

컴파일러가 [SomeClass someMethod]과 같은 정적 참조를 성공적으로 가져 오려면 링크 할 대상이 필요합니다.

위와 같이 메커니즘을 연결하면 Foundation과 Apple이 추가 클래스를 추가 할 때 메커니즘이 작동한다는 것이 맞습니다. NSJSONSerialization이 있는지 확인하는 것과 같습니다.

존재하지 않을 수도있는 프레임 워크와 약한 링크가있는 경우에도 작동합니다. 그래서 예. 당신은 Twitter.framework에 대한 연약한 연결을 할 수 있고 [TWRequest alloc] ...을 사용할 수 있습니다. Twitter 프레임 워크가 전혀없는 iOS 4에서 빌드하고 배포 할 수 있습니다.

Apple은 실제로 라이브러리가 저장되는 방식을 약간 수정하여 약한 링크가있는 NSClassFromString 대신에 if([TWRequest class]) 또는 무엇이든 사용하도록 허용하고 있습니다.

그러나 정적 라이브러리에 링크하거나 링크하지 않으려는 것처럼 들리겠습니까? 따라서 클래스는 런타임에 사용 가능할 수도 있고 사용 가능하지 않을 수도 있지만 링커에게 보이거나 보이지 않을 수도 있습니다.

이 경우 메타 클래스에 대한 문자 참조를 피하면됩니다. 그래서 당신은 같은 일을 할 수있는 :

Class someClassMetaClass = NSClassFromString(@"SomeClass"); 

if(someClassMetaClass) 
{ 
    SomeClass *instance = [[someClassMetaClass alloc] init]; 
    /* ... */ 
} 

만큼 헤더 파일은 컴파일러 (즉, 어쨌든 바이너리로하지 않기 때문에) 당신이 포인터에 대한 SomeClass 유형을 지정할 수있는 행복과 의지 것입니다 볼 수 있습니다로 게시 된 인터페이스에 대한 일반적인 자동 완성 및 경고를 제안 할 수 있어야합니다. 그냥 항상 직접보다는 런타임에서 가져온 Class에 대한 포인터를 통해 메타 클래스를 지정해야합니다. 그렇게하면 링커가 후속 조치를 취할 필요가 없습니다.

+0

감사합니다. 라이트 버전에서 누락 된 몇 가지 클래스가있는 "전체"및 "라이트"변형이있는 라이브러리를 구축하고 있습니다. 클래스가 존재하는지 아닌지에 따라 몇 가지 다른 클래스 동작이 있습니다. – Gruntcakes

관련 문제