RunTime1. 对象、类对象、元类对象
2. 消息传递机制
3. 消息转发流程
4. Method Swizzling (交换方法)
5. class_addMethod (动态添加方法)
6. objc_getAssociatedObject objc_setAssociatedObject
主要 RunTime文章:
Objective-C特性:Runtime
让你快速上手Runtime
iOS 程序员 6 级考试(答案和解释)
Swift RunTime 视频:
Swift RunTime
OC是一门弱类型语言、动态语言,区别于C语言等面向过程编程(编译时就确定了调用哪个函数),区别于Swift强类型语言编译时有语法错误会实时提示,OC一些隐藏的BUG不会提示(如URL为空等情况)。OC编译时并不确定调用哪个函数,运行时才确定调用哪个函数,即SEL(函数编号)编译时不确定调用哪个IMP(函数指针),SEL -> IMP(映射关系)。
我们一般用OC动态特性使用一些RunTime黑魔法,如交换方法,动态添加属性,动态添加方法,RunTime底层使用C进行一层封装,OC方法再对RunTime进行一层封装。
1、消息传递机制
导入头文件 #import <objc/message.h>,Build Settings 中 Enable Strict Checking of objc_msgSend Calls 至为NO。
创建类Person,实现eat方法,调用eat方法的几种方式:
1> Person *person = [[Person alloc] init]; [person eat];
2> [person performSelector:@selector(eat)];
3> objc_msgSend(person,@selector(eat));
堆栈区别:
堆:程序员自己alloc手动创建的。
栈:系统分配的。
导入头文件 #import <objc/runtime.h>
2、交换方法
获取SEL函数编号:
sel_registerName("") -> SEL
NSSelectorFromString(@"") -> SEL
获取类:
NSClassFromString(@"") -> Class
objc_getClass("") -> Class
// APP在手机的硬盘里,当加载类到内存的时候调用load方法
+ (void)load;
获取类方法:
class_getClassMethod(self, @selector(imageWithName:)) -> Method
获取类对象方法(实例方法)
class_getInstanceMethod(Class,SEL)
// 交换两个方法的实现,一般用于给系统自带方法添加额外的方法
method_exchangeImplementations(Method_Nonnull m1, Method_Nonnull m2)
3、动态添加方法
1) Q:子类继承父类的方法,子类里面有父类的方法吗?
A:没有,系统查找子类中没有该方法时,会往上查找子类的父类。只有子类override(重载、重写)时才有这个方法,调用super继承父类的属性行为。
// 当这个类调用了一个没有实现的类方法,可动态添加方法
+(BOOL)resolveClassMethod:(SEL)sel;
// 当这个类调用了一个没有实现的实例方法,可动态添加方法
+(BOOL)resolveInstanceMethod:(SEL)sel;
// 动态添加eat方法
// 第一个参数:给哪个类添加方法
// 第二个参数:添加方法的方法编号
// 第三个参数:添加方法的函数实现(函数地址)
// 第四个参数:函数的类型,(返回值+参数类型) v:void @:对象->self :表示SEL->_cmd
class_addMethod(self, @selector(eat), eat, "v@:");
4.给分类添加属性
NSObject *objc = [[NSObject alloc] init];
objc.name = @"小码哥"; // Set
NSLog(@"%@",objc.name); // Get
// 定义关联的key
static const char *key = "name";
- (NSString *)name
{
// 根据关联的key,获取关联的值。
return objc_getAssociatedObject(self, key);
}
- (void)setName:(NSString *)name
{
// 第一个参数:给哪个对象添加关联
// 第二个参数:关联的key,通过这个key获取
// 第三个参数:关联的value
// 第四个参数:关联的策略
objc_setAssociatedObject(self, key, name, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
网友评论