대상 C : ID와 void의 차이 *
-
19-09-2019 - |
문제
차이점은 무엇입니까? id
그리고 void *
?
해결책
void *
"유형이없는/알 수없는 내용을 가진 임의의 청크 O '메모리에 대한 참조"를 의미합니다.
id
"알 수없는 클래스의 임의 대상 C 객체에 대한 언급"을 의미합니다.
추가 의미 적 차이가 있습니다.
GC 전용 또는 GC 지원 모드에서 컴파일러는 유형의 참조에 대한 쓰기 장벽을 방출합니다.
id
, 그러나 유형은 아닙니다void *
. 구조를 선언 할 때 이것은 중요한 차이가 될 수 있습니다. Ivars가 좋아하는 선언void *_superPrivateDoNotTouch;
IF가있는 개체를 조기 수확 할 것입니다_superPrivateDoNotTouch
실제로 대상입니다. 그렇게하지 마십시오.참조에서 메소드를 호출하려고 시도합니다
void *
유형은 컴파일러 경고를 바꾸게됩니다.An에서 메소드를 호출하려고 시도합니다
id
유형은 호출되는 방법이@interface
컴파일러가 본 선언.
따라서 물체를 void *
. 마찬가지로, 사용을 피해야합니다 id
객체를 참조 할 입력 된 변수. 가장 구체적인 클래스 타이핑 참조를 사용하십시오. 조차 NSObject *
~보다 낫다 id
컴파일러는 적어도 해당 참조에 대한 메소드 호출의 더 나은 검증을 제공 할 수 있기 때문입니다.
일반적이고 유효한 하나의 사용 void *
다른 API를 통해 전달되는 불투명 데이터 참조입니다.
고려하다 sortedArrayUsingFunction: context:
의 방법 NSArray
:
- (NSArray *)sortedArrayUsingFunction:(NSInteger (*)(id, id, void *))comparator context:(void *)context;
분류 함수는 다음과 같이 선언됩니다.
NSInteger mySortFunc(id left, id right, void *context) { ...; }
이 경우 Nsarray는 단지 당신이 전달하는 모든 것을 context
그 방법을 통한 방법에 대한 인수 context
논쟁. NSARRAY에 관한 한 포인터 크기의 데이터의 불투명 한 덩어리이며 원하는 목적으로 자유롭게 사용할 수 있습니다.
언어의 클로저 유형 기능이 없으면 기능이 포함 된 데이터 덩어리를 수행하는 유일한 방법입니다. 예시; MySortFunc ()가 조건부로 사례에 민감하거나 사례 무의미한 것으로 정렬되기를 원한다면 여전히 스레드-안전한 경우에도 컨텍스트에서 IS- 사례에 민감한 표시기를 전달하여 출시 중에 캐스팅 될 수 있습니다.
연약하고 오류가 발생하기 쉽지만 유일한 방법입니다.
블록은 이것을 해결합니다 -블록은 C의 클로저입니다. Clang에서 사용할 수 있습니다. http://llvm.org/ 그리고 스노우 레오파드에서 널리 퍼져 있습니다 (http://developer.apple.com/library/ios/documentation/performance/gcd_libdispatch_ref/gcd_libdispatch_ref.pdf).
다른 팁
ID는 void*가 무엇이든 포인터 인 목표 C 객체에 대한 포인터입니다.
ID는 또한 알 수없는 mthods를 호출하는 것과 관련된 경고를 꺼냅니다.
[(id)obj doSomethingWeirdYouveNeverHeardOf];
알 수없는 방법에 대한 일반적인 경고를 제공하지 않습니다. 물론 OBJ가 NIL이거나 실제로 해당 방법을 구현하지 않는 한 런타임에 예외를 제기 할 것입니다.
종종 당신은 사용해야합니다 NSObject*
또는 id<NSObject>
선호합니다 id
, 반환 된 물체가 코코아 객체임을 확인하므로 유지/릴리스/autoreLease와 같은 방법을 안전하게 사용할 수 있습니다.
메소드에 리턴 유형이있는 경우 id
목표 C 객체를 반환 할 수 있습니다.
void
메소드는 아무것도 반환하지 않습니다.
void *
포인터 일뿐입니다. 포인터가 가리키는 주소에서 컨텐츠를 편집 할 수 없습니다.
id
목표 C 객체에 대한 포인터입니다. void *
포인터입니다 아무것. 당신은 사용할 수 있습니다 void *
대신에 id
, 그러나, 당신은 아무것도 컴파일러 경고를받지 않기 때문에 권장되지 않습니다.
보고 싶을 수도 있습니다 stackoverflow.com/questions/466777/whats-the-difference-between-declaring-a-variable-and-nsobject 그리고 unixjunkie.blogspot.com/2008/03/id-vs-nsobject-vs-id.html.
/// Represents an instance of a class.
struct objc_object {
Class isa OBJC_ISA_AVAILABILITY;
};
/// A pointer to an instance of a class.
typedef struct objc_object *id;
위의 코드는 OBJC.H에서 나온 것이므로 ID는 OBJC_Object struct의 인스턴스 인 것처럼 보이며 ISA 포인터는 모든 목적 C 클래스 객체와 바인딩 할 수 있지만 void*는 단지 유형의 포인터입니다.
내 이해는 ID가 객체에 대한 포인터를 나타내는 반면 void *는 실제로 무엇이든 지적 할 수 있다는 것입니다.
이미 말한 것 외에도 컬렉션과 관련된 객체와 포인터 사이에는 차이가 있습니다. 예를 들어, NSARRAY에 무언가를 넣으려면 ( "ID"유형의 객체가 필요하며, 유형의 "void *"의 원시 데이터 포인터를 사용할 수 없습니다. 당신이 사용할 수있는 [NSValue valueWithPointer:rawData]
변환하다 void *rawDdata
컬렉션 내부에서 사용하기위한 "ID"유형으로. 일반적으로 "ID"는 더 유연하며 첨부 된 물체와 관련된 의미론이 더 많습니다. 설명하는 더 많은 예가 있습니다 ID 유형의 목표 c는 여기에 있습니다.