OC是一门动态语言,其动态性主要表现在以下三个方面:
1.动态类型:例如OC中的id类型,会在程序运行的过程中,根据环境确定真实的类型;
2.动态加载:根据需求加载所需要的资源;
3.动态绑定:OC的消息机制
正是由于OC的这种特性,这就使得OC不仅需要一个编译器,还需要一个运行时系统,这个运行时系统就是runtime。由于苹果的封闭性,在XCode5之后想要使用runtime需要进行一定的设置,如下图。
在使用runtime之前,我们先要了解一下OC的消息机制,即OC中方法的调用实际上是一种消息机制,某个对象或者进行方法调用的时候会调用runtime的objc_msgSend函数,根据传入的对象,以及方法选择器SEL去寻找需要调用的方法。在OC中runtime主要有以下几个作用:
1.交换方法
在开发过程中,可能系统系统的方法达不到需求,进行扩展。进行扩展时有两种方法,一种是建立一个继承自父类的子类,重写父类的方法;第二种就是使用runtime进行方法交换。交换方法的步骤很简单,以UIImage中的imageNamed:方法为例,创建一个分类,在分类加载的时候完成方法交换,以下是分类中的实现。通过方法交换,可以扩展系统自带方法。
+ (void)load {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
// 获取需要交换的方法
Method imageName = class_getClassMethod(self, @selector(imageName:));
Method imageNamed = class_getClassMethod(self, @selector(imageNamed:));
// 交换方法实现
method_exchangeImplementations(imageName, imageNamed);
});
}2.动态加载方法
当一个类中的方法很多时,加载这个类是非常消耗资源的,此时可以使用runtime中的动态加载方法,解决问题。动态加载方法需要使用performSelector方法
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
Dog *dog = [[Dog alloc] init];
[dog performSelector:@selector(run)];
}
@implementation Dog
void run(id self, SEL _cmd)
{
NSLog(@"%@,%@", self, NSStringFromSelector(_cmd));
}
// 在该方法中动态调用方法
+ (BOOL)resolveInstanceMethod:(SEL)sel
{
if (sel == @selector(run)) {
class_addMethod(self, @selector(run), (IMP)run, "V@:"); return YES;
}
return [super resolveInstanceMethod:sel];
}
这样就能够实现动态添加方法。(了解更多动态添加方法点这里:http://tech.glowing.com/cn/objective-c-runtime/)3.动态添加属性
给某个类动态添加属性是在该类的分类中实现的,首先在分类中定义一个需要添加的属性,在分类实现中重写属性的getter/setter方法。
- (void)setName:(NSString *)name
{
// 第一个参数:需要关联的对象
// 第二个参数:关联的key,获取的时候也是通过这个key来获取
// 第三个参数:关联的属性
// 第四个参数:关联的策略
// 添加关联
objc_setAssociatedObject(self, @"name", name, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (NSString *)name
{
// 获取关联
return objc_getAssociatedObject(self, @"name");
}
runtime还可以实现字典数组转模型数组的操作,这个方法还在学习中,以后理解了再更新这篇博客。
本文介绍了Objective-C的Runtime机制,包括动态类型、动态加载与动态绑定等特性。详细讲解了如何利用Runtime交换方法、动态加载方法及动态添加属性,并提供了具体的代码实例。
1997

被折叠的 条评论
为什么被折叠?



