XM Zhang
XM Zhang

Reputation: 123

What is meaning of -(Class)class?

This is my sample code:

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

View is a class, now I have some confusion:

  1. v1 is an instance of View, and View is an instance of View's meta class, right?
  2. return value of [v1 class] is an pointer named isa point to class object, right?
  3. return value of [View class] is an pointer named isa point to meta class, right?
  4. 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
    
  5. 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 ??

Edit

I got some informations from apple document, type method of -class and instance method of class, the two method have same return value, named class object, what's this ? the instance of meta class ?? and how to get metaclass ?

Upvotes: 0

Views: 84

Answers (1)

rob mayoff
rob mayoff

Reputation: 385580

  1. v1 is an instance of View, and View is an instance of View's meta class, right?

v1 is an instance of View.

You cannot use View as a regular C identifier, only as the recipient of class messages (like [View new]), but there is a real object that receives those class messages. It's common and convenient to call that the View class object, and it is the only instance of the View metaclass.

  1. return value of [v1 class] is an pointer named isa point to class object, right?

[v1 class] returns a reference to the View class object. The isa “pointer” is an implementation detail and in fact its implementation has changed. See “Non-pointer isa”.

  1. return value of [View class] is an pointer named isa point to meta class, right?

[View class] means exactly the same thing as [View self]. Both return the View class object, not a metaclass object. You can see this in the Objective-C runtime source code. I will quote the relevant method definitions here.

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

When you say [View self], it runs the +[NSObject self] method quoted above, with the local variable self pointing to the View class object. (Whew, that's a lot of “self”!) So [View self] returns the View class object:

- (id)self {
    return self;
}

When you say [v1 self], it runs the -[NSObject self] method quoted above, with the local variable self pointing to the v1 object (a View instance). So [v1 self] returns v1.

+ (Class)class {
    return self;
}

When you say [View class], it runs the +[NSObject class] method quoted above, with the local variable self pointing to the View class object. So [View class] returns the View class object, just like [View self] does.

- (Class)class {
    return object_getClass(self);
}

When you say [v1 class], it runs the -[NSObject class] method quoted above, with the local variable self pointing to the v1 object (a View instance). This method has a different body than the three other methods above. This method uses the Objective-C runtime function object_getClass to get a reference to the View class object.

  1. 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
    

As I explained above, both of these return the View class object.

  1. 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] returns the same thing as [View self]: the View class object. If you want to get a reference to the View metaclass object, you need to use the Objective-C runtime directly, like this:

NSLog(@"%p", object_getClass([View class]));

Note that if you print [View class] with %@, it just prints View. And if you print object_getClass([View class]) with %@, it also just prints View. You cannot distinguish between the View class object and the View metaclass object by their string descriptions. You have to look at the pointer values (which is indeed what you were doing).

Here is my test:

#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;
}

Here is the output (with NSLog fluff removed):

v1 = <View: 0x101600780> / 0x101600780
[v1 class] = View / 0x1000011e0
[[v1 class] class] = View / 0x1000011e0
[View class] = View / 0x1000011e0
object_getClass([View class]) = View / 0x1000011b8

So:

  • my v1 object is at 0x101600780,
  • the View class object is at 0x1000011e0,
  • and the View metaclass object is at 0x1000011b8.

You might wonder why [View class] returns the View class object instead of the View metaclass object. Greg Parker is the main Apple employee who maintains the Objective-C runtime, and he explains why in 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 that NSObject->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.

Upvotes: 2

Related Questions