Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

RunTime 之方法交换 #4

Open
Open
Labels
RunTimeExtra attention is needed
@aTreey

Description

以前只是看到过运行时相关的资料,现在项目中依然在用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

        AltStyle によって変換されたページ (->オリジナル) /