zoukankan      html  css  js  c++  java
  • iOS开发系列-Runtime运用场景

    概述

    Runtime 又叫运行时,是一套底层的 C 语言 API,其为 iOS 内部的核心之一,我们平时编写的 OC 代码,底层都是基于它来实现的。
    调用runtimeAPI需要导入都文件#import <objc/runtime.h>

    常用的runtime函数

    // 获取一个类的Class类型(类对象)
    objc_getClass(const char * _Nonnull name)
    
    // 获取函数的IMP
    class_getMethodImplementation(Class cls,  SEL name)
    
    // 获取对象某个方法
    Method method = class_getInstanceMethod(Class cls, SEL  name)
    
    // 获取类的某个方法
    Method method = class_getClassMethod(Class cls, SEL  name);
    
    // 交换方法
    method_exchangeImplementations(Method  _Nonnull m1, Method  _Nonnull m2)
    
    // 动态给类添加方法
    class_addMethod(Class cls, SEL name, IMP imp, const char *  types);
    
    // 获取类的成员
    class_copyIvarList(Class cls, unsigned int * outCount);
    

    runtime使用场景

    利用类扩展给对象添加属性

    在类扩展中给类添加属性,默认只会生成属性的getter与setter方法声明,不会生成方法实现和带下划线成员变量
    示例: 给UIView添加一个NSDictinonary和flag属性 ,flag为BooL类型,作为基本类型属性的代表

    #import <UIKit/UIKit.h>
    
    @interface UIView (Example)
    
    // 动态添加基本数据类型成员变量
    @property (nonatomic, assign) BOOL flag;
    
    // 动态添加对象类型成员变量
    @property (nonatomic, strong) NSDictionary *dict;
    @end
    
    #import "UIView+Example.h"
    #import <objc/runtime.h>
    
    @implementation UIView (Example)
    /***************************动态添加基本数据类型成员变量***************************/
    - (void)setFlag:(BOOL)flag
    {
        // 注意:参数二 需要传递一个key 这里建议用@selector(属性名),不用定义很多常量
        objc_setAssociatedObject(self, @selector(flag), @(flag), OBJC_ASSOCIATION_ASSIGN);
    }
    
    - (BOOL)flag
    {
        id object = objc_getAssociatedObject(self, @selector(flag));
        return object?[object boolValue]: NO;
    }
    
    /***************************动态添加对象类型成员变量***************************/
    -(void)setDict:(NSDictionary *)dict
    {
        objc_setAssociatedObject(self, @selector(dict), dict, OBJC_ASSOCIATION_RETAIN);
    }
    
    - (NSDictionary *)dict
    {
        return objc_getAssociatedObject(self, @selector(dict));
    }
    @end
    

    动态添加方法

    class_addMethod(Class  _Nullable cls, SEL name, IMP  imp, const char * types);
    

    第一个参数:类对象 可以通过objc_getClass获取 第二个参数 动态添加的方法SEL
    第三个参数 方法或者函数的实现地址 class_getMethodImplementation 方法实现
    第四个参数:描述方法/函数的返回值类型、参数类型 使用@encode()可获得类型的编码

    下面示例给ViewController添加一个addNewMethod:方法,然后通过performSelector 在程序运行时调用该方法。

    // 动态添加的方法
    - (void)addNewMethod:(UIButton *)button
    {
        NSLog(@"-------------------%@", button);
    }
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        
        // 1.获取动态添加方法的地址IMP
        IMP addNewMethodIMP = class_getMethodImplementation([self class], @selector(addNewMethod:));
        
        // 2.获取方法的types
        char types[100];
        strcpy(types, @encode(void)); // 返回值类型
        strcpy(types, @encode(id)); // 每个函数自带的id self参数
        strcpy(types, @encode(SEL)); // 每个函数自带的SEL sel参数
        strcpy(types, @encode(UIButton)); // 动态添加方法addNewMethod的button参数
        
        // 3.动态绑定添加方法
        class_addMethod(objc_getClass("ViewController"), @selector(addNewMethod:), addNewMethodIMP, types);
    }
    
    - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
    {
        // 通过performSelector调用函数
        [self performSelector:@selector(addNewMethod:) withObject:UIButton.new];
    }
    

    方法交换

    程序在启动是会加载开发者编写的类,在方法的调用时动态的去查找方法的实现。如果实现方法交换的思路时在程序加载时交换方法的实现。

  • 相关阅读:
    归一化与标准化区别
    pytorch进行mnist识别实战
    pytorch实现学习率衰减
    RNN
    Python中9大时间序列预测模型
    InfluxDB基本概念
    如何在CentOS 7上使用InfluxDB分析系统指标(转载学习用)
    InfluxDB1.2.4部署(centos7)
    Centos7搭建influxdb+chronograf
    python通过SNMP协议收集服务器监控信息
  • 原文地址:https://www.cnblogs.com/CoderHong/p/9431763.html
Copyright © 2011-2022 走看看