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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-14 22:12:52  来源:igfitidea点击:

Why id is generic pointer?

objective-ciosxcodepointersvoid-pointers

提问by User97693321

I want to know why idis a weak reference pointer,how it is able to handle any classtype 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 是弱引用指针?

idis 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 idprovides 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 idas being the supertype of every Objective-C class, and it treats iddifferently. 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 isapointer, and that's how Apple's runtime finds out the class of every1object. The idtype is defined to have this information as well. In fact, its only attribute is the isapointer, 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 idreference 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 isapointer 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 -classto 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 isMemberOfClassinstead 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, ...);