iOS底层学习-day-14
前言-OC-runtime篇
我是一名iOS开发者, iOS底层 菜鸟的进阶之路30天。
问题
讲一下 OC 的消息机制
- OC中的方法调用其实都是转成了objc_msgSend函数的调用,给receiver(方法调用者)发送了一条消息(selector方法名)
- objc_msgSend底层有3大阶段
- 消息发送(当前类、父类中查找)、动态方法解析、消息转发
[self class], [self superclass], [super class], [super superclass]
- (instancetype)init {
if (self = [super init]) {
NSLog(@"[self class] = %@", [self class]); // MJStudent
NSLog(@"[self superclass] = %@", [self superclass]); // MJPerson
NSLog(@"--------------------------------");
// objc_msgSendSuper({self, [MJPerson class]}, @selector(class));
NSLog(@"[super class] = %@", [super class]); // MJStudent 因为还是去找NSObject类,所以,还是找到了传进去还是当前类,self还是receiver消息接受者,那还是object_getClass(self);
NSLog(@"[super superclass] = %@", [super superclass]); // MJPerson
}
return self;
}
- class 和 superclass
- (Class)class {//class底层实现,self还是receiver消息接受者
return object_getClass(self);
}
- (Class)superclass {//superclass底层实现,self还是receiver消息接受者
return class_getSuperclass(object_getClass(self));
}
消息转发
- (id)forwardingTargetForSelector:(SEL)aSelector {
if (aSelector == @selector(test)) {
// objc_msgSend([[MJCat alloc] init], aSelector)
return [[MJCat alloc] init];
}
return [super forwardingTargetForSelector:aSelector];
}
//如果消息转发为空
- (id)forwardingTargetForSelector:(SEL)aSelector {
if (aSelector == @selector(test)) {
return nil;
}
return [super forwardingTargetForSelector:aSelector];
}
// 方法签名:返回值类型、参数类型
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
if (aSelector == @selector(test)) {
return [NSMethodSignature signatureWithObjCTypes:"v16@0:8"];
}
return [super methodSignatureForSelector:aSelector];
}
// NSInvocation封装了一个方法调用,包括:方法调用者、方法名、方法参数
// anInvocation.target 方法调用者
// anInvocation.selector 方法名
// [anInvocation getArgument:NULL atIndex:0]
- (void)forwardInvocation:(NSInvocation *)anInvocation {
// anInvocation.target = [[MJCat alloc] init];
// [anInvocation invoke];
[anInvocation invokeWithTarget:[[MJCat alloc] init]];
}
@synthesize 和 @dynamic
- @synthesize
//现在不用写,因为编译器会自动生成_age
@synthesize age = _age, height = _height;
- @dynamic
// 提醒编译器不要自动生成setter和getter的实现、不要自动生成成员变量
@dynamic age;