답변:
void *
"형식화되지 않은 / 알 수없는 내용의 임의의 청크 메모리에 대한 참조"를 의미합니다.
id
"알 수없는 클래스의 임의의 Objective-C 객체에 대한 참조"를 의미합니다.
추가적인 의미 차이가 있습니다.
GC Only (GC 전용) 또는 GC Supported (GC 지원) 모드에서 컴파일러는 type 참조가 id
아닌 쓰기 장벽 을 생성합니다 void *
. 구조를 선언 할 때 이것은 중요한 차이가 될 수 있습니다. iVars를 선언 void *_superPrivateDoNotTouch;
하면 _superPrivateDoNotTouch
실제로 객체 인 경우 객체를 조기에 수확하게됩니다 . 하지마
void *
유형 의 참조에서 메소드를 호출하려고 시도 하면 컴파일러 경고가 표시됩니다.
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 ()가 조건에 따라 대소 문자를 구분하거나 대소 문자를 구분하지 않도록하려면 상황에 따라 대 / 소문자를 구분하는 표시기를 전달합니다.
깨지기 쉽고 오류가 발생하기 쉽지만 유일한 방법입니다.
블록은 이것을 해결합니다-블록은 C의 클로저입니다. Clang에서 사용할 수 있습니다-http: //llvm.org/ 및 Snow Leopard ( http://developer.apple.com/library/ios/documentation/Performance /Reference/GCD_libdispatch_Ref/GCD_libdispatch_Ref.pdf ).
id
응답 내용에 대한 가정은 없습니다 . 은 id
쉽게에서 고유하지 않는 클래스의 인스턴스를 참조 할 수 있습니다 NSObject
. 실제적으로 말하면, 당신의 진술은 실제 행동과 가장 일치합니다. <NSObject>
구현 되지 않은 클래스를 Foundation API와 혼합 하여 멀리 갈 수는 없습니다. 확실히 확실합니다!
id는 목적 C 객체에 대한 포인터이며, void *는 모든 것에 대한 포인터입니다.
id는 알 수없는 mthod 호출과 관련된 경고도 해제합니다. 예를 들면 다음과 같습니다.
[(id)obj doSomethingWeirdYouveNeverHeardOf];
알 수없는 방법에 대한 일반적인 경고를 제공하지 않습니다. 물론 obj가 nil이거나 실제로 해당 메소드를 구현하지 않는 한 런타임에 예외가 발생합니다.
종종 당신은 사용해야 NSObject*
나 id<NSObject>
에 우선 id
당신이 안전하게에 / 해제 / 오토 릴리즈를 유지하는 등의 방법을 사용할 수 있도록 적어도 확인한다에 반환되는 객체는, 코코아 객체입니다.
Often you should use NSObject*
대신에 동의하지 않습니다 id
. 지정 NSObject*
하면 실제로 객체가 NSObject라고 명시 적으로 말합니다. 객체에 대한 모든 메소드 호출은 경고가 발생하지만 해당 객체가 실제로 메소드 호출에 응답하는 한 런타임 예외는 없습니다. 경고는 분명히 성가 시므로 id
더 좋습니다. 예를 들어 id<MKAnnotation>
,이 경우 객체가 무엇이든 관계없이 MKAnnotation 프로토콜을 준수해야합니다.
id
Objective-C 객체에 대한 포인터입니다. 아무것도void *
가리키는 포인터 입니다. 대신에 사용할 수 있지만 컴파일러 경고가 전혀 발생하지 않으므로 권장하지 않습니다.void *
id
stackoverflow.com/questions/466777/whats-the-difference-beclaring-a-variable-id-and-nsobject 및 unixjunkie.blogspot.com/2008/03/id-vs-nsobject-vs 를 참조하십시오. -id.html .
void *
형식화 된 변수는 메서드 호출의 대상이 될 수 있습니다. 오류가 아니라 경고입니다. 뿐만 아니라 int i = (int)@"Hello, string!";
다음과 같이 할 수 있습니다 printf("Sending to an int: '%s'\n", [i UTF8String]);
. 오류가 아니라 경고 (정확히 권장되거나 휴대용이 아님)입니다. 그러나 이런 일을 할 수있는 이유는 모두 기본적인 C입니다.
내 이해는 id가 객체에 대한 포인터를 나타내는 반면 void *는 사용하려는 유형으로 캐스팅하는 한 실제로 무엇이든 가리킬 수 있다는 것입니다.
이미 말한 것 외에도 컬렉션과 관련된 객체와 포인터 사이에는 차이가 있습니다. 예를 들어, NSArray에 무언가를 넣으려면 "id"유형의 객체가 필요하며 "void *"유형의 원시 데이터 포인터를 사용할 수 없습니다. 컬렉션 내에서 사용하기 위해 "id"형식 [NSValue valueWithPointer:rawData]
으로 변환하는 void *rawDdata
데 사용할 수 있습니다 . 일반적으로 "id"는 더 유연하며 연결된 객체와 관련된 의미가 더 많습니다. Objective C의 id 유형을 설명하는 더 많은 예제가 있습니다 .
id
에 대응하는 가정-retain
하고-release
A는 반면,void*
호출 수신자에 완전히 불투명하다.-performSelector:withObject:afterDelay:
(객체를 유지 하는) 임의의 포인터를 전달할 수 없으며+[UIView beginAnimations:context:]
컨텍스트를 유지 한다고 가정 할 수 없습니다 (애니메이션 대리자는 컨텍스트의 소유권을 유지해야하고 UIKit은 애니메이션 대리자를 유지합니다).