Skip to content

3.1.7

Compare
Choose a tag to compare
@MoLice MoLice released this 25 Apr 14:11
· 203 commits to master since this release

重要说明

以前版本的 QMUI 代码里 swizzle 的方案大都是用 QMUIRuntime.h 里的 ExchangeImplementations() 函数,但这种方式在某些情况下会导致代码不以预期方式运行(具体可看下方,或者 #567),因此这个版本里,我们修改了以前的另一个用于 swizzle 的函数 OverrideImplementation(),以 block 的方式去写 swizzle 后的方法内容,并解决 ExchangeImplementations() 的问题,建议以后默认都用这种方式去 swizzle,不再使用 ExchangeImplementations()

对于新方式,被 swizzle 的方法 return 值类型、参数数量及类型都会影响语法,所以我们提供了多个 Code Snippet 简化这个过程,具体可查看 QMUI iOS Code Snippets 里以 extendoverride 开头的系列,其中 extend 表示自动帮你先调用 super 的实现,再调用你自己的实现,所以只需要直接写你的实现即可,语法简洁,而 override 适用于需要手动管理 super 的调用时机(或者屏蔽 super 的调用),语法较为复杂,建议借助 Code Snippet 的占位符提示。以下是对应的 Code Snippet 汇总:

  • override_void_non_argv - 用 OverrideImplementation() 重写指定 class 的某个无返回值、无参数的方法实现
  • override_void_single_argv - 用 OverrideImplementation() 修改指定 class 的某个无返回值、带一个参数的方法实现
  • override_void_two_argvs - 用 OverrideImplementation() 修改指定 class 的某个无返回值、带两个参数的方法实现
  • override_return_non_argv - 用 OverrideImplementation() 修改指定 class 的某个带返回值、无参数的方法实现
  • override_return_single_argv - 用 OverrideImplementation() 修改指定 class 的某个带返回值、带一个参数的方法实现
  • override_return_two_argvs - 用 OverrideImplementation() 修改指定 class 的某个带返回值、带两个参数的方法实现
  • extend_void_non_argv - 用 ExtendImplementationOfVoidMethodWithoutArguments() 修改指定 class 的某个无返回值、无参数的方法实现
  • extend_void_single_argv - 用 ExtendImplementationOfVoidMethodWithSingleArgument() 修改指定 class 的某个无返回值、带一个参数的方法实现
  • extend_void_two_argvs - 用 ExtendImplementationOfVoidMethodWithTwoArguments() 修改指定 class 的某个无返回值、带两个参数的方法实现
  • extend_return_non_argv - 用 ExtendImplementationOfNonVoidMethodWithoutArguments() 修改指定 class 的某个带返回值、无参数的方法实现
  • extend_return_single_argv - 用 ExtendImplementationOfNonVoidMethodWithSingleArgument() 修改指定 class 的某个带返回值、带一个参数的方法实现
  • extend_return_two_argvs - 用 ExtendImplementationOfNonVoidMethodWithTwoArguments() 修改指定 class 的某个带返回值、带两个参数的方法实现

extend_void_non_argv 重写 [UIView layoutSubviews] 示例:

extend_void_non_argv

override_void_non_argv 重写 [UIView layoutSubviews] 示例:

override_void_non_argv

会带来 QMUI 新旧版本兼容问题的更新

  1. 修改 OverrideImplementation 的参数类型,从而避免子类先 swizzle 后父类再 swizzle 同一个方法,会导致子类里丢失父类 swizzle 后的方法内容的问题。

如何适配新版

  1. 全局搜索 SEL originCMD, IMP originIMP,将其替换为 SEL originCMD, IMP (^originalIMPProvider)(void)
  2. 全局搜索 )originIMP;,将其替换为 )originalIMPProvider();
  3. 以后的 swizzle 需求建议都是用上文提到的 OverrideImplementation() 实现。

Bugfix

  1. #567 修复以静态库方式引入 QMUI 时会因为编译顺序的问题导致某些 swizzle 方法失效的 bug。
  2. #569 避免 _performBatchUpdates:completion: 私有 API 导致审核被拒绝的问题。
  3. #570 修复 UIScrollView 使用 qmui_maskedCorners 时会出现显示错误的 bug。
  4. 修复 NSObject (QMUI) -qmui_performSelector:withArguments: 会丢失第二个及以后的参数的 bug。