Skip to content

RunTime 之方法交换 #4

@aTreey

Description

@aTreey

以前只是看到过运行时相关的资料,现在项目中依然在用UIWebView 最近打算给WebView 加一个假的进度条,所以打算通过使用RunTimeUIWebView 增加分类关联属性和方法的方式实现

方法交换

  • class_getInstanceMethod(Class _Nullable cls, SEL _Nonnull name) 获取cls类的实例方法,

    • cls 要获取实例方法的相关类,
    • name 需要获取类的实例方法名称
  • class_getClassMethod(Class _Nullable cls, SEL _Nonnull name) 获取cls类的类方法,

    • cls 要获取实例方法的相关类,
    • name 需要获取类的类方法名称
  • method_getImplementation 获取一个方法的IMP(方法的实现),具体是指implement

  • method_getTypeEncoding 获取一个方法实现的Type字符串,包括参数类型和返回值类型

  • class_addMethod(Class _Nullable cls, SEL _Nonnull name, IMP _Nonnull imp, const char * _Nullable types) 添加一个新的方法,

    • cls: 需要被添加的类
    • SEL: 要被添加的方法 例如:@selector(webViewDidFinishLoad:)
    • IMP: 添加的方法实现地址,例如:(IMP)my_webViewDidFinishLoad
    • types: 方法实现的Type字符串,包括参数类型和返回值类型
       无参无返回值: "V@:"
       有参无返回值:  "i@:"  返回值为`int`类型
       有参有返回值: "i@:@"  返回值为`int`类型,有一个参数
    
    • 返回值为BOOl
    • 保证即便originalSelector只在父类中实现,也能达到Method Swizzling的目的, 比如一个方法只是在父类中实现而在子类中未实现,class_addMethod就会执行返回值为YES以达到方法替换,
    • 如果子类本身实现了这个方法,返回值为NO,然后我们只需要直接执行class_replaceMethod方法就可以达到目的
  • class_replaceMethod(Class _Nullable cls, SEL _Nonnull name, IMP _Nonnull imp, const char * _Nullable types) 替换类中添加成功的方法的实现, 如果该方法不存在就会添加该方法, 覆盖执行class_addMethod然后再替换换两个方法实现

  • method_exchangeImplementations(Method _Nonnull m1, Method _Nonnull m2) 交换两个已经存在的方法实现

交换方法代码示例参考

给分类关联属性和方法

  • objc_getAssociatedObject(id _Nonnull object, const void * _Nonnull key) 给get方法关联值,返回与给定键的特定对象关联的值

  • objc_setAssociatedObject(id _Nonnull object, const void * _Nonnull key, id _Nullable value, objc_AssociationPolicy policy)set方法关联值,

    • object:要关联的源对象
    • key:关联时标记是哪一个属性的key,用于区分关联的多个属性,可以用 _cmd代替, _cmd 在Objective-C的方法中表示当前方法的selector,正如同self表示当前方法调用的对象实例一样,每个方法都是不一样的
    • value: 关联的对象
    • policy:关联策略

Metadata

Metadata

Assignees

No one assigned

    Labels

    RunTimeExtra attention is needed

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions