xcode 为什么 id 是通用指针?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7871368/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why id is generic pointer?
提问by User97693321
I want to know why id
is a weak reference pointer,how it is able to handle any class
type pointer and at run time how can we detect that which type of class pointer is assigned to id
.
我想知道为什么id
是弱引用指针,它如何能够处理任何class
类型的指针,以及在运行时我们如何检测分配给了哪种类型的类指针id
。
回答by
Why is id a weak reference pointer?
为什么 id 是弱引用指针?
id
is not a weak reference pointer, at least not in the ARC ownership sense. Whether an id
-typed reference to an object is weak or not depends on the reference having been declared __weak
(and variations) and the object's class actually supporting weak references.
id
不是弱引用指针,至少在 ARC 所有权意义上不是。id
对对象的类型化引用是否弱取决于已声明的引用__weak
(和变体)以及实际支持弱引用的对象类。
However, you could say that id
provides weak typing, although I think that dynamic/duck typing is a more accurate description. Since an id
- typed reference contains no compile-time class-type information, the compiler isn't able to, for example, determine if the underlying object can respond to a given selector, which could lead to runtime errors.
但是,您可以说id
提供了弱类型,尽管我认为动态/鸭子类型是更准确的描述。由于id
- 类型的引用不包含编译时类类型信息,例如,编译器无法确定底层对象是否可以响应给定的选择器,这可能会导致运行时错误。
How is it able to handle any class type pointer?
它如何能够处理任何类类型指针?
That's part of the definition of the Objective-C language. The compiler recognises id
as being the supertype of every Objective-C class, and it treats id
differently. See the answer below as well.
这是Objective-C 语言定义的一部分。编译器将其id
视为每个 Objective-C 类的超类型,并对其进行id
不同的处理。请参阅下面的答案。
At runtime, how can we detect that which type of class pointer is assigned to id?
在运行时,我们如何检测分配给 id 的是哪种类型的类指针?
In Apple's Objective-C runtime, the first bytes in the memory allocated to an object must point to that object's class. You might see this referenced elsewhere as the isa
pointer, and that's how Apple's runtime finds out the class of every1object. The id
type is defined to have this information as well. In fact, its only attribute is the isa
pointer, which means that all1Objective-C objects conform to this definition.
在 Apple 的 Objective-C 运行时,分配给对象的内存中的第一个字节必须指向该对象的类。您可能会在其他地方看到 this 作为isa
指针引用,这就是 Apple 的运行时找出每1 个对象的类的方式。该id
类型也被定义为具有此信息。事实上,它唯一的属性就是isa
指针,这意味着所有1个Objective-C对象都符合这个定义。
If you have an id
reference and want to discover the class of the referenced object, you can send it -class
:
如果你有一个id
引用并且想发现被引用对象的类,你可以发送它-class
:
id someObject;
// Assign something to someObject
// Log the corresponding class
Class c = [someObject class];
NSLog(@"class = %@", c);
// Test whether the object is of type NSString (or a subclass of NSString)
if ([someObject isKindOfClass:[NSString class]]) {
NSLog(@"it's a string");
}
1Tagged pointersare a notable deviation of this structure, and (partly) because of them one shouldn't access the isa
pointer directly.
1标记指针是此结构的一个显着偏差,并且(部分)因此不应isa
直接访问指针。
回答by morningstar
It's nice to have a generic object type, so you can define collection types that can hold any kind of object, and other generic services that work with any object without knowing what kind of object it is.
有一个通用的对象类型很好,这样你就可以定义可以容纳任何类型对象的集合类型,以及可以在不知道它是什么类型的对象的情况下处理任何对象的其他通用服务。
There is no trick to make id work. At a binary level all pointers are interchangeable. They just represent a memory address as a numerical value. To make id accept any type of pointer, it's only necessary to disablethe rules of the compiler that normally require pointer types to match.
没有使 id 工作的技巧。在二进制级别,所有指针都是可互换的。它们只是将内存地址表示为数值。要使 id 接受任何类型的指针,只需禁用通常需要指针类型匹配的编译器规则。
You can find out information about the class of an id type variable in these kinds of ways:
您可以通过以下几种方式找到有关 id 类型变量的类的信息:
id theObject = // ... something
Class theClass = [theObject class];
NSString *className = NSStringFromClass(theClass);
NSClassDescription *classDescription = [NSClassDescription classDescriptionForClass:theClass];
But it's rarely necessary to do those kinds of things in code. More often, you want to test if your id variable is an instance of a particular class, and if so cast it to that class and start treating it as that type.
但是很少需要在代码中做这些事情。更常见的是,您想测试您的 id 变量是否是特定类的实例,如果是,则将其强制转换为该类并开始将其视为该类型。
if ([theObject isKindOfClass:[MySpecializedClass class]]) {
MySpecializedClass *specialObject = (MySpecializedClass *)theObject;
[specialObject doSomethingSpecial];
}
If you were to use -class
to find out the class, but it returned a class you know nothing about, then there's nothing special you can do with the object based on its class anyway. So there is no reason to do anything but check if it matches classes you know about, and only if you intend to do special handling for those classes anyway.
如果您要使用-class
来查找类,但它返回了一个您一无所知的类,那么无论如何您都无法根据其类对对象进行任何特殊处理。因此,除了检查它是否与您知道的类匹配外,没有理由做任何事情,并且仅当您打算对这些类进行特殊处理时才这样做。
You can sometimes use isMemberOfClass
instead of isKindOfClass
. It depends whether you want an exact match or to include subclasses.
有时您可以使用isMemberOfClass
代替isKindOfClass
. 这取决于您是想要完全匹配还是包含子类。
回答by shakthi
It may be worth to take a look on header file objc/objc.h to find internals of id
.
可能值得查看头文件 objc/objc.h 以找到id
.
typedef struct objc_class *Class;
typedef struct objc_object {
Class isa;
} *id;
typedef struct objc_selector *SEL;
typedef id (*IMP)(id, SEL, ...);