这是我的示例代码:
View *v1 = [View new];
NSLog(@"%d",([v1 isKindOfClass:[View class]]));
NSLog(@"%d",([[v1 class] isKindOfClass:[View class]]));
View
是一个类,现在我有些困惑:
- v1 是 View 的实例,View 是 View 的元类的实例,对吗?
[v1 class]
的返回值是一个名为isa
的指针,指向类对象,对吗?[View class]
的返回值是一个名为isa
的指针指向元类,对吧?我记录了
[v1 class]
和[View class]
的地址,它们是相等的,为什么?NSLog(@"%p", [v1 class]); NSLog(@"%p", [View class]); 2018-01-05 10:47:30.554190+0800 Block[16532:785147] 0x10a61a178 2018-01-05 10:47:30.554300+0800 Block[16532:785147] 0x10a61a178
我猜重点是
[View class]
的返回值,所以如果[View class]
的返回值没有指向它的元类,它是谁??它指向谁??
编辑
我从苹果文档中得到了一些信息,type method of -class和 instance method of class ,这两个方法有相同的返回值,名为class object
,这是什么?元类的实例??以及如何获取元类?
最佳答案
- v1 is an instance of View, and View is an instance of View's meta class, right?
v1
是 View
的实例。
您不能将View
用作常规的C标识符,只能用作类消息的接收者(如[View new]
),但是有一个真实的对象接收那些类消息。调用 View
类对象很常见也很方便,它是 View
元类的唯一实例。
- return value of
[v1 class]
is an pointer namedisa
point to class object, right?
[v1 class]
返回对 View
类对象的引用。 isa
“指针”是一个实现细节,实际上它的实现已经改变了。参见 “Non-pointer isa” .
- return value of
[View class]
is an pointer namedisa
point to meta class, right?
[View class]
与 [View self]
的含义完全相同。两者都返回 View
类对象,而不是元类对象。你可以在 the Objective-C runtime source code 中看到这个.我会在这里引用相关的方法定义。
+ (id)self {
return (id)self;
}
当你说[View self]
时,它运行上面引用的+[NSObject self]
方法,局部变量self
指向到 View
类对象。 (哇,有很多“self”!)因此 [View self]
返回 View
类对象:
- (id)self {
return self;
}
当你说 [v1 self]
时,它运行上面引用的 -[NSObject self]
方法,局部变量 self
指向到 v1
对象(一个 View
实例)。所以 [v1 self]
返回 v1
。
+ (Class)class {
return self;
}
当你说[View class]
时,它运行上面引用的+[NSObject class]
方法,局部变量self
指向到 View
类对象。所以 [View class]
返回 View
类对象,就像 [View self]
一样。
- (Class)class {
return object_getClass(self);
}
当你说[v1 class]
时,它运行上面引用的-[NSObject class]
方法,局部变量self
指向到 v1
对象(一个 View
实例)。此方法的主体与上述其他三种方法不同。此方法使用 Objective-C 运行时函数 object_getClass
获取对 View
类对象的引用。
I log address of [v1 class] and [View class], they are equal, why?
NSLog(@"%p", [v1 class]); NSLog(@"%p", [View class]); 2018-01-05 10:47:30.554190+0800 Block[16532:785147] 0x10a61a178 2018-01-05 10:47:30.554300+0800 Block[16532:785147] 0x10a61a178
正如我上面所解释的,这两个都返回 View
类对象。
- I guess the key point is the return value of [View class], so if the return value of [View class] does not point to its meta class, who is it ?? who is it point to ??
[View class]
返回与 [View self]
相同的东西:View
类对象。如果要获取对 View
元类对象的引用,则需要直接使用 Objective-C 运行时,如下所示:
NSLog(@"%p", object_getClass([View class]));
请注意,如果您使用 %@
打印 [View class]
,它只会打印 View
。如果您使用 %@
打印 object_getClass([View class])
,它也只会打印 View
。您无法通过字符串描述来区分 View
类对象和 View
元类对象。您必须查看指针值(这确实是您正在做的)。
这是我的测试:
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
@interface View: NSObject
@end
@implementation View
@end
int main(int argc, const char * argv[]) {
@autoreleasepool {
View *v1 = [View new];
NSLog(@"v1 = %@ / %p", v1, v1);
NSLog(@"[v1 class] = %@ / %p", [v1 class], [v1 class]);
NSLog(@"[[v1 class] class] = %@ / %p", [[v1 class] class], [[v1 class] class]);
NSLog(@"[View class] = %@ / %p", [View class], [View class]);
NSLog(@"object_getClass([View class]) = %@ / %p", object_getClass([View class]), object_getClass([View class]));
}
return 0;
}
这是输出(删除了 NSLog
绒毛):
v1 = <View: 0x101600780> / 0x101600780
[v1 class] = View / 0x1000011e0
[[v1 class] class] = View / 0x1000011e0
[View class] = View / 0x1000011e0
object_getClass([View class]) = View / 0x1000011b8
所以:
- 我的
v1
对象位于 0x101600780, View
类对象位于 0x1000011e0,View
元类对象位于 0x1000011b8。
您可能想知道为什么 [View class]
返回View
类对象而不是View
元类对象. Greg Parker 是维护 Objective-C 运行时的主要 Apple 员工,他在 a blog post titled “Classes and metaclasses” 中解释了原因。 :
Objective-C uses metaclasses for practical goals like class methods, but otherwise tends to hide metaclasses. For example,
[NSObject class]
is identical to[NSObject self]
, even though in formal terms it ought to return the metaclass thatNSObject->isa
points to. The Objective-C language is a set of practical compromises; here it limits the class schema before it gets too, well, meta.
关于ios - -(Class)class 是什么意思?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48106850/