OC-runtime使用场景

在实际开发中,Objective-C 的运行时(runtime)是一个强大的特性,它允许开发者在程序运行时动态地操作类、对象、方法等,以下是一些常见的使用场景:

  1. 关联对象

    有时需要为类添加额外的属性,但又不想修改类的声明。通过 runtime 可以为类的实例动态地关联额外的数据。例如,在一个第三方库提供的类中,我们想为它添加一个自定义的标识属性,就可以使用关联对象来实现。

    objc

    less 复制代码
    #import <objc/runtime.h>
    
    @interface UIButton (CustomProperty)
    @property (nonatomic, copy) NSString *customIdentifier;
    @end
    
    @implementation UIButton (CustomProperty)
    - (void)setCustomIdentifier:(NSString *)customIdentifier {
        objc_setAssociatedObject(self, @selector(customIdentifier), customIdentifier, OBJC_ASSOCIATION_COPY_NONATOMIC);
    }
    
    - (NSString *)customIdentifier {
        return objc_getAssociatedObject(self, @selector(customIdentifier));
    }
    @end
  2. 方法交换

    这是一种非常有用的技术,用于在不修改原有方法实现的基础上,对方法的行为进行修改或扩展。比如在应用中,我们想统计某个方法的调用次数或在方法调用前后添加一些日志记录。

    objc

    less 复制代码
    Method originalMethod = class_getInstanceMethod([UIViewController class], @selector(viewDidLoad));
    Method swappedMethod = class_getInstanceMethod([UIViewController class], @selector(myViewDidLoad));
    method_exchangeImplementations(originalMethod, swappedMethod);
    
    - (void)myViewDidLoad {
        NSLog(@"ViewDidLoad method start");
        [self myViewDidLoad];
        NSLog(@"ViewDidLoad method end");
    }
  3. 动态创建类和对象

    在运行时可以动态地创建类,然后实例化对象。这在一些框架或插件系统中很有用,比如根据配置文件中的类名动态地创建类实例。

    objc

    less 复制代码
    Class newClass = objc_allocateClassPair([NSObject class], "MyDynamicClass", 0);
    // 添加属性和方法
    class_addProperty(newClass, "dynamicProperty", propertyAttributes);
    class_addMethod(newClass, @selector(dynamicMethod), (IMP)dynamicMethodImplementation, methodTypes);
    objc_registerClassPair(newClass);
    
    id instance = [[newClass alloc] init];
  4. 获取类的信息

    可以使用 runtime 获取类的属性列表、方法列表、协议列表等信息。这在实现一些自动序列化、反射机制或代码生成工具时非常有用。

    objc

    ini 复制代码
    unsigned int propertyCount;
    objc_property_t *properties = class_copyPropertyList([MyClass class], &propertyCount);
    for (unsigned int i = 0; i < propertyCount; i++) {
        const char *propertyName = property_getName(properties[i]);
        NSLog(@"Property: %s", propertyName);
    }
    free(properties);
  5. 消息转发机制

    当一个对象接收到无法响应的消息时,runtime 会启动消息转发流程。通过重写相关的消息转发方法,可以实现更灵活的消息处理。比如在一个代理模式中,当代理对象无法处理某个消息时,可以将消息转发给其他对象处理。

    objc

    python 复制代码
    - (id)forwardingTargetForSelector:(SEL)aSelector {
        if ([self.anotherObject respondsToSelector:aSelector]) {
            return self.anotherObject;
        }
        return [super forwardingTargetForSelector:aSelector];
    }

这些只是 runtime 在实际开发中的一部分应用,它为开发者提供了高度的灵活性和扩展性,能够实现很多强大的功能。

相关推荐
陈随易6 小时前
在 VSCode 里,把项目一键部署到服务器
前端·后端·程序员
Highcharts.js7 小时前
教程:基于 React + Highcharts 构建一个单页应用程序、按需数据拉取与图表渲染
开发语言·前端·数据结构·react.js·前端框架·highcharts·页面应用
To_OC7 小时前
我被 useState 坑了两次之后,终于把它的脾气摸透了
前端·javascript·react.js
鱼樱前端7 小时前
我用 Claude Code 后,编码效率翻 3 倍。但更值钱的是别的。
前端·后端·ai编程
_lucas7 小时前
给知识库网站接入AI问答
前端·ai编程·全栈
前端糕手8 小时前
前端面试题大全:JavaScript + Vue3 + React + TypeScript + 工程化 + 性能优化
前端
我不叫武9 小时前
一个用 Rust 写的离线编码查询桌面工具
前端
Web4Browser10 小时前
指纹浏览器 API 自动化怎么接:启动 Profile、获取 CDP 端点并连接自动化框架
前端·网络·typescript·自动化
Patrick_Wilson10 小时前
从 React 到 Flutter:写给前端的一张跨端知识地图
前端·flutter·react.js
颜酱10 小时前
06 | 把 meta_config 同步进 MySQL(生成阶段)
前端·人工智能·后端