1. super call function essence
The underlying implementation of the class method:
// Get the class of the caller object - (Class)class { return object_getClass(self); } // Get the husband class of the caller object - (Class)superclass { return class_getSuperclass(object_getClass(self)); }
The underlying implementation of super [the underlying implementation of [super message]:
1. The message recipient is still a subclass object.
2. Find the implementation of the method from the parent class.
Example:
#import "Person.h" @interface Student : Person @end
#import <Foundation/Foundation.h> @interface Person : NSObject - (void)run; @end
- (instancetype)init { if (self = [super init]) { NSLog(@"[self class] = %@", [self class]); // Student NSLog(@"[self superclass] = %@", [self superclass]); // Person NSLog(@"--------------------------------"); /** * super Call implementation essence: * objc_msgSendSuper({self, [Person class]}, @selector(class)); */ NSLog(@"[super class] = %@", [super class]); // Student NSLog(@"[super superclass] = %@", [super superclass]); // Person } return self; } @end
2. Differences between isMemberOfClass and isKindOfClass
First look at the underlying logic:
- (BOOL)isMemberOfClass:(Class)cls { return [self class] == cls; } - (BOOL)isKindOfClass:(Class)cls { for (Class tcls = [self class]; tcls; tcls = tcls->superclass) { if (tcls == cls) return YES; } return NO; } + (BOOL)isMemberOfClass:(Class)cls { return object_getClass((id)self) == cls; } + (BOOL)isKindOfClass:(Class)cls { for (Class tcls = object_getClass((id)self); tcls; tcls = tcls->superclass) { if (tcls == cls) return YES; } return NO; }
Example 1:
id person = [[MJPerson alloc] init]; // Judge whether the instance object on the left is equal to the class on the right NSLog(@"%d", [person isMemberOfClass:[MJPerson class]]); // 1 NSLog(@"%d", [person isMemberOfClass:[NSObject class]]); // 0 // Judge whether the instance object on the left belongs to the class or subclass on the right NSLog(@"%d", [person isKindOfClass:[MJPerson class]]); // 1 NSLog(@"%d", [person isKindOfClass:[NSObject class]]); // 1
Example 2:
NSLog(@"%d", [NSObject isKindOfClass:object_getClass([NSObject class])]); // 1 NSLog(@"%d", [NSObject isMemberOfClass:object_getClass([NSObject class])]); // 1 NSLog(@"%d", [NSObject isKindOfClass:object_getClass([MJPerson class])]); // 0 NSLog(@"%d", [MJPerson isMemberOfClass:object_getClass([MJPerson class])]); // 1 // ------- // The method caller of this code returns YES no matter which class it is (as long as it is in the NSObject system) NSLog(@"%d", [NSObject isKindOfClass:[NSObject class]]); // 1 NSLog(@"%d", [NSObject isMemberOfClass:[NSObject class]]); // 0 NSLog(@"%d", [MJPerson isKindOfClass:[MJPerson class]]); // 0 NSLog(@"%d", [MJPerson isMemberOfClass:[MJPerson class]]); // 0
Summary:
1. Instance method is the judgment of class:
1. isMemberOfClass: judge whether the instance object on the left is equal to the class on the right
2. isKindOfClass: judge whether the instance object on the left belongs to the class or subclass on the right
2. Class method is the judgment of metaclass:
1. Under normal circumstances, the parameter transfer should take the metaclass object for judgment.
2. If it is judged by passing class objects, all returned values are 0; Unless the input parameter on the right is [NSObject class], the method caller returns YES regardless of the class (as long as it is in the NSObject system).
3. Can the following code be executed successfully? If yes, what is the print result?
Knowledge points:
1. Essence of super call
2. Allocation of function stack space
3. Message mechanism
4. Accessing the nature of member variables
1. Pointer analysis
1. At this time, cls stores the address of MJPerson class
2. obj is a pointer to the address of the MJPerson class
3,MJPerson.name is a member variable in the mjversion structure, which is located in the next stack of isa.
4. Because MJPerson is not initialized, the actual situation is that the name attribute is not converted to a member variable and becomes a variable in the heap.
5. Therefore, at this time, self The value obtained by name is the next stack information of MJPerson structure isa.
2. [super viewDidLoad] essential analysis
Underlying structure:
struct abc = { self, [ViewController class] }; objc_msgSendSuper2(abc, sel_registerName("viewDidLoad"));
From this underlying structure, mjperson The next address of ISA is self, and the next address is [ViewController class]. The heap address information is as follows:
3. Stack analysis
4. Print value
- (void)print { NSLog(@"my name is %@", self.name); }
self.name actually takes the next address [self->\u name] of isa in mjversion structure, and the next address of isa in mjversion structure is the instance object of self in ViewController.
To sum up, the final print ed value is the self object.
verification: