为什么 id 是通用指针?

发布于 2024-12-11 16:08:40 字数 85 浏览 0 评论 0原文

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

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

一江春梦 2024-12-18 16:08:40

为什么 id 是弱引用指针?

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

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

它如何能够处理任何类类型指针?

这是目标定义的一部分- C语言。编译器将 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标记指针是该结构的一个显着偏差,并且(部分)由于它们,人们不应该直接访问 isa 指针。

Why is id a weak reference pointer?

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.

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.

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.

At runtime, how can we detect that which type of class pointer is assigned to 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 every1 object. The id type is defined to have this information as well. In fact, its only attribute is the isa pointer, which means that all1 Objective-C objects conform to this definition.

If you have an id reference and want to discover the class of the referenced object, you can send it -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 pointers are a notable deviation of this structure, and (partly) because of them one shouldn’t access the isa pointer directly.

黑色毁心梦 2024-12-18 16:08:40

拥有通用对象类型是件好事,因此您可以定义可以容纳任何类型对象的集合类型,以及可与任何对象一起使用的其他通用服务,而无需知道该对象是什么类型。

没有任何技巧可以让 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。这取决于您是想要精确匹配还是包含子类。

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 disable the rules of the compiler that normally require pointer types to match.

You can find out information about the class of an id type variable in these kinds of ways:

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.

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.

You can sometimes use isMemberOfClass instead of isKindOfClass. It depends whether you want an exact match or to include subclasses.

只是在用心讲痛 2024-12-18 16:08:40

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

It may be worth to take a look on header file objc/objc.h to find internals of id.

typedef struct objc_class *Class;
typedef struct objc_object {
   Class isa;
} *id;


typedef struct objc_selector    *SEL;    
typedef id          (*IMP)(id, SEL, ...); 
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文