前言
iOS开发者都知道,runtime和GCD在实际开发中有多重要,在此仅记录我本人在开发中对于前者最常用的应用和感受,具体详细介绍不在赘述。想了解可自行百度,谷歌。
iOS Runtime详解
iOS 模式详解—「runtime&runloop 面试、工作」
Objective-C Runtime 深入了解
正题
关联对象(Objective-C Associated Objects)给类增加属性。即在既有类中使用关联对象存放自定义数据。
使用关联对象时,若想令两个键匹配到同一个值,则两者需为完全相同的指针,鉴于此,通常用静态全局变量做键。
实际开发中,有以下几中写法:
#import "objc/runtime.h"
@interface NSObject (runtime)
@property (nonatomic, copy) NSString *test;
@end
@implementation NSObject (runtime)
//1.使用静态常量
//static char kTestKey;
//static void * const kTestKey = &kTestKey;
static const void * kTestKey = "kTestKey";
- (void)setTest:(NSString *)test {
objc_setAssociatedObject(self, kTestKey, test, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
//2.使用方法名
//objc_setAssociatedObject(self, @selector(setTest:), test, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (NSString *)test {
return objc_getAssociatedObject(self, kTestKey);
//return objc_getAssociatedObject(self, _cmd);
//return objc_getAssociatedObject(self, @selector(setTest:));
}
@end
方法调配(Method Swizzling)给类添加或替换方法。
@implementation ViewController
+ (void)load {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
Class class = [self class];
SEL originalSelector = @selector(viewDidLoad);
SEL swizzledSelector = @selector(testViewDidLoad);
Method originalMethod = class_getInstanceMethod(class, originalSelector);
Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);
//判断原方法存在
BOOL didAddMethod = class_addMethod(class, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod));
// if swizzledMethod is already existed.
if (didAddMethod) {
class_replaceMethod(class, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));
}
else {
method_exchangeImplementations(originalMethod, swizzledMethod);
}
});
}
- (void)testViewDidLoad {
//替换方法
[self testViewDidLoad];
}
- (void)viewDidLoad {
//原方法
[super viewDidLoad];
}
@end
看上去好像陷入递归调用的死循环,但是此方法是和原方法互换的,所以在运行期,替换方法的选择子(selector)实际上对应于原有方法的实现。
其他应用
动态变量控制,私有属性赋值/取值
实现NSCoding的自动归/解档
实现字典和模型的自动转换 等等
以上应用并不频繁,不再多说。
总之runtime在实际开发中十分便捷,不过我了解的只是皮毛,对于对象、消息、运行期还需要更深层次的理解。