Runtime是OC中的黑魔法。个人在项目中使用到Runtime的地方比较少,主要是以下两种:
1.动态为类添加属性:主要使用场景为类目(category)添加属性。
这里的例子是为UIButton+Suggest添加属性propertyA。
@interface UIButton (Suggest)
@property(nonatomic,strong) NSString *propertyA;
@end
@implementation UIButton (Suggest)
staticchar*PropertyA ="PropertyA";
-(void)setPropertyA:(UITabBarController*)propertyA {
/*
OBJC_ASSOCIATION_ASSIGN;//assign策略
OBJC_ASSOCIATION_COPY_NONATOMIC;//copy策略
OBJC_ASSOCIATION_RETAIN_NONATOMIC;// retain策略
OBJC_ASSOCIATION_RETAIN;
OBJC_ASSOCIATION_COPY;
*/
/*
* id object给哪个对象的属性赋值
const void *key属性对应的key
id value设置属性值为value
objc_AssociationPolicy policy使用的策略,是一个枚举值,和copy,retain,assign是一样的,手机开发一般都选择NONATOMIC
objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy);
*/
objc_setAssociatedObject(self,PropertyA, propertyA,OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (NSString*)propertyA {
return objc_getAssociatedObject(self,PropertyA);
}
2.方法交换:使用场景主要是在iOS中实现面向切面编程思想。
下面是Mattt大神在NSHipster上的文章自己写的代码。
#import "UIViewController+swizzling.h"
#import
@implementation UIViewController (swizzling)
//load方法会在类第一次加载的时候被调用
//调用的时间比较靠前,适合在这个方法里做方法交换
+ (void)load{
//方法交换应该被保证,在程序中只会执行一次
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
//获得viewController的生命周期方法的selector
SEL systemSel = @selector(viewWillAppear:);
//自己实现的将要被交换的方法的selector
SEL swizzSel = @selector(swiz_viewWillAppear:);
//两个方法的Method
Method systemMethod = class_getInstanceMethod([self class], systemSel);
Method swizzMethod = class_getInstanceMethod([self class], swizzSel);
//首先动态添加方法,实现是被交换的方法,返回值表示添加成功还是失败
BOOL isAdd = class_addMethod(self, systemSel, method_getImplementation(swizzMethod), method_getTypeEncoding(swizzMethod));
if (isAdd) {
//如果成功,说明类中不存在这个方法的实现
//将被交换方法的实现替换到这个并不存在的实现
class_replaceMethod(self, swizzSel, method_getImplementation(systemMethod), method_getTypeEncoding(systemMethod));
}else{
//否则,交换两个方法的实现
method_exchangeImplementations(systemMethod, swizzMethod);
}
});
}
- (void)swiz_viewWillAppear:(BOOL)animated{
//这时候调用自己,看起来像是死循环
//但是其实自己的实现已经被替换了
[self swiz_viewWillAppear:animated];
NSLog(@"swizzle");
}
@end
在一个自己定义的viewController中重写viewWillAppear
- (void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
NSLog(@"viewWillAppear");
}
关于Runtime实用的,还有一种是动态生成Model,网上有很多优秀的例子,这里就不说了。
这篇是关于Runtime实用的,先到这里。希望大家指点出不足与错误之处。
网友评论