Runtime - 运行时

简介

  • 运行时是一种面向对象的编程语言的运行环境,类似于 java 的虚拟机
  • OC 最主要的特点就是在程序运行时,以发送消息的方式调用方法
  • 运行时是 OC 的核心,Objective-C 就是基于运行时的

  • 参考文档:http://nshipster.cn/swift-objc-runtime/

利用 clang 生成中间代码

  • 进入终端
  • 输入以下命令:
$ clang -rewrite-objc main.m
  • 可以将 OC 的代码重写成 C++ 的代码

运行时在开发中的主要应用场景

  • 字典转模型
  • 给分类增加关联对象,开发框架时解耦
  • 交换方法,在无法修改系统或者第三方框架的方式时
    • 利用交换方法,先执行自己的方法
    • 再执行系统或第三方框架的方法
    • 黑魔法,对系统/框架版本有很强的依赖性

交换方法演练

  • 导入头文件并且从 AFN 的 AFURLSessionManager.m 中复制两个静态函数
#import <objc/runtime.h>

static inline void af_swizzleSelector(Class theClass, SEL originalSelector, SEL swizzledSelector) {
    // 获取对象的原始方法
    Method originalMethod = class_getInstanceMethod(theClass, originalSelector);
    // 获取对象的要交换的方法 - 必须先添加方法
    Method swizzledMethod = class_getInstanceMethod(theClass, swizzledSelector);
    // 交换方法
    method_exchangeImplementations(originalMethod, swizzledMethod);
}

static inline BOOL af_addMethod(Class theClass, SEL selector, Method method) {
    // 添加方法
    return class_addMethod(theClass, selector,  method_getImplementation(method),  method_getTypeEncoding(method));
}
  • 新建 UIImageView+Hack 分类,实现以下代码
#import "UIImageView+Hack.h"
#import <objc/runtime.h>

@implementation UIImageView (Hack)

+ (void)load {

    Method swizzledMethod = class_getInstanceMethod([UIImageView class], @selector(cz_setImage:));
    Method originalMethod = class_getInstanceMethod([UIImageView class], @selector(setImage:));

    // 交叉方法
    method_exchangeImplementations(swizzledMethod, originalMethod);
}

/// 设置图像
///
/// @param image UIImage
- (void)cz_setImage:(UIImage *)image {

    CGSize size = self.bounds.size;
    UIGraphicsBeginImageContextWithOptions(size, YES, 0);

    [image drawInRect:self.bounds];

    UIImage *result = UIGraphicsGetImageFromCurrentImageContext();

    UIGraphicsEndImageContext();

    // 调用系统默认方法
    [self cz_setImage:result];
}

@end

运行测试,使用模拟器的 Debug - Color Misaligned Images 测试

posted @ 2016-10-11 15:09  笔锋至此  阅读(157)  评论(0编辑  收藏  举报