为什么id是通用指针?

时间:2011-10-24 04:41:08

标签: objective-c ios xcode pointers void-pointers

我想知道为什么id是弱引用指针,它是如何处理任何class类型指针的,并且在运行时我们如何检测分配了哪种类型的类指针id

3 个答案:

答案 0 :(得分:17)

  

为什么id是弱引用指针?

id不是弱引用指针,至少不是ARC所有权意义上的指针。对象的id类型引用是否弱是取决于已声明__weak(和变体)的引用,而对象的类实际上支持弱引用。

但是,你可以说id提供弱类型,虽然我认为动态/鸭子类型是更准确的描述。由于id类型的引用不包含编译时类类型信息,因此编译器无法确定底层对象是否可以响应给定的选择器,这可能导致运行时错误。

  

如何处理任何类类型指针?

这是the Objective-C language定义的一部分。编译器将id识别为每个Objective-C类的超类型,并以不同方式处理id。请参阅下面的答案。

  

在运行时,我们如何检测哪个类指针被分配给id?

在Apple的Objective-C运行时,分配给对象的内存中的第一个字节必须指向该对象的类。您可能会在其他地方将此引用为isa指针,这就是Apple的运行时查找每个 1 对象的类的方式。 id类型也定义为包含此信息。实际上,它唯一的属性是isa指针,这意味着所有 1 Objective-C对象都符合这个定义。

如果您有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");
}

1 Tagged pointers是这种结构的显着偏差,并且(部分)因为它们不应该直接访问isa指针。

答案 1 :(得分:8)

拥有通用对象类型很好,因此您可以定义可以包含任何类型对象的集合类型,以及可以在不知道对象类型的情况下使用任何对象的其他通用服务。

没有诀窍让id工作。在二进制级别,所有指针都是可互换的。它们只是将内存地址表示为数值。要使id接受任何类型的指针,只需要禁用通常需要指针类型匹配的编译器规则。

您可以通过以下几种方式找到有关id类型变量类的信息:

id theObject = // ... something
Class theClass = [theObject class];
NSString *className = NSStringFromClass(theClass);
NSClassDescription *classDescription = [NSClassDescription classDescriptionForClass:theClass];

但是很少有必要在代码中做这些事情。更常见的情况是,您希望测试您的id变量是否是特定类的实例,如果是,则将其强制转换为该类并开始将其视为该类型。

if ([theObject isKindOfClass:[MySpecializedClass class]]) {
    MySpecializedClass *specialObject = (MySpecializedClass *)theObject;
    [specialObject doSomethingSpecial];
}

如果您要使用-class查找该类,但它返回了一个您一无所知的类,那么无论如何您都无法使用基于其类的对象做任何特殊操作。所以没有理由做任何事情,但检查它是否与你所知道的课程相匹配,并且只有你打算对这些课程进行特殊处理。

您有时可以使用isMemberOfClass代替isKindOfClass。这取决于您是想要完全匹配还是包含子类。

答案 2 :(得分:3)

查看头文件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, ...);