余额不足.

initialize使用不当造成的问题

字数统计: 599阅读时长: 2 min
2018/07/19 Share

事件由来

之前项目中有个让用户一边签署协议,一边录制视频上传的功能,当时法务同学要求的是只能直接拍摄上传,不能让用户在相册里直接选取,然后就有了只能拍摄视频上传的第一个版本。而当用户使用之后表示不能从相册中选取很不方便,有时签署协议过程中出了些问题的话又得重新操作一遍。
收到反馈之后,产品也迅速的给出了方案,在原来的的基础上添加一个本地上传的功能,于是我想到了个骚操作。
15319807710011

原本这个拍照按钮调用的是系统的拍摄视频,但我直接给替换成了之前同事写的直接拍摄上传了。
考虑到之前做启动优化, +load 方法如果越多,app冷启动速度就会越慢,我就将搅拌方法放在了 +initialize中,然后,意想不到的bug发生了。

BUG

测试小姐姐告诉我线上H5调用相机拍照调不起来,app直接卡死,daily调相机则会直接crash。然而native直接调用的话确是可以的。

寻找原因

native调用的是 PhotoSelectorViewControlle,而H5调用的则是 WebPhotoSelectorViewController,这两个控制的关系就是 WebPhotoSelectorViewController 继承自 PhotoSelectorViewControlle

WebPhotoSelectorViewController+initialize 方法中下断点,如果native直接调用的话,改方法只执行了一遍,而H5调用的话 +initialize 却是执行了两遍,why ???
15319823192834

15319823744881

以上两张图的执行结果表示了第一次方法替换是成功了,但第二次就出现问题了,方法变成了第一次已经替换成功之后的方法,然后在之后的方法就造成了死循环。

1
2
3
4
5
6
7
- (void)swizz_pushImagePickerController {
if (条件成立) {
// doSomestring
return;
}
[self swizz_pushImagePickerController];
}

那么问题来了,为什么+initialize执行了两遍?

之前看load与initialize的异同的时候看见过一张图,
15319828915111

如果子类未实现+initialize方法的话,是会沿用父类的实现的,这也就是为啥+initialize执行了两遍。
15319830988438

参照官方文档,PhotoSelectorViewControlle的initialize先执行了一遍,而WebPhotoSelectorViewController没有实现initialize,则再一次的执行了父类的initialize。如果不想子类调用父类的initialize,则需要和上图中代码款一样操作就行了。

CATALOG
  1. 1. 事件由来
  2. 2. BUG
  3. 3. 寻找原因