什么是 - (班级)班级的意思?

时间:2018-01-05 03:31:19

标签: ios objective-c

这是我的示例代码:

View *v1 = [View new];
NSLog(@"%d",([v1 isKindOfClass:[View class]]));
NSLog(@"%d",([[v1 class] isKindOfClass:[View class]]));

View是一个班级,现在我有些困惑:

  1. v1是View的一个实例,View是View的元类的实例,对吗?
  2. [v1 class]的返回值是一个名为isa的指针指向类对象,对吗?
  3. [View class]的返回值是一个名为isa的指针指向元类,对吗?
  4. 我记录[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
    
  5. 我猜关键点是[View class]的返回值,所以如果[View class]的返回值没有指向它的元类,那么它是谁?谁指出??

  6. 修改

    我从apple文档type method of -classinstance method of class获得了一些信息,这两个方法具有相同的返回值,名为class object,这是什么?元类的实例??以及如何获得元类?

1 个答案:

答案 0 :(得分:2)

  
      
  1. v1是View的一个实例,View是View的元类的一个实例,对吗?
  2.   

v1View的实例。

您不能将View用作常规C标识符,仅作为类消息的接收者(如[View new]),但有一个真实对象接收这些类消息。调用View类对象是常见且方便的,它是View元类的唯一实例。

  
      
  1. [v1 class]的返回值是一个名为isa的指针指向类对象,对吗?
  2.   

[v1 class]返回对View类对象的引用。 isa“指针”是一个实现细节,实际上它的实现已经改变。请参阅“Non-pointer isa”

  
      
  1. [View class]的返回值是一个名为isa的指针指向元类,对吗?
  2.   

[View class][View self]完全相同。两者都返回View类对象,而不是元类对象。您可以在the Objective-C runtime source code中看到此信息。我将在这里引用相关的方法定义。

+ (id)self {
    return (id)self;
}

当您说[View self]时,它会运行上面引用的+[NSObject self]方法,局部变量self指向View类对象。 (哇,那很多“自我”!)所以[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类对象的引用。

  
      
  1. 我记录[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
    
  2.   

如上所述,这两个都返回View类对象。

  
      
  1. 我猜关键点是[View class]的返回值,所以如果[View class]的返回值没有指向它的元类,那么它是谁?是谁指向??
  2.   

[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使用元类来实现像类方法这样的实际目标,但是否则会隐藏元类。例如,[NSObject class][NSObject self]相同,即使在正式术语中它应该返回NSObject->isa指向的元类。 Objective-C语言是一套实际的妥协;在这里它限制了类模式,然后, meta