黑魔法(method-swizzling)解决第三方库引发的问题
需求
最近做一個項(xiàng)目中,有個需求,所有網(wǎng)絡(luò)請求,都不顯示 NetworkActvityIndicator(也就是狀態(tài)欄里旋轉(zhuǎn)的小圈圈).
解決過程1:
全局搜索 NetworkIndicator 關(guān)鍵字, 把所有涉及 NetworkIndicator 的代碼去除,比如 [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES]; 。
測試并發(fā)現(xiàn)新問題
所有界面都不再顯示NetworkActvityIndicator了,唯獨(dú)一個播放視頻的界面依然顯示。
猜想: 第三方庫引發(fā)的問題
無論是哪些第三方庫,正常情況都會通過 setNetworkActivityIndicatorVisible 來 顯示狀態(tài)欄小圈圈。
驗(yàn)證過程1
通過繼承 UIApplication 來重寫了 setNetworkActivityIndicatorVisible 方法。(如何繼承UIApplication,請看這里)并把斷點(diǎn)打在這個方法體內(nèi)。
測試了正常調(diào)用 [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES]; 是會觸發(fā)斷點(diǎn)的。但是唯獨(dú)那個視頻界面,沒有觸發(fā)該斷點(diǎn)的情況下,正常顯示小圈圈。
驗(yàn)證過程2
通過 KVO 監(jiān)聽 UIApplication 的 networkActivityIndicatorVisible 屬性,結(jié)果還是和 驗(yàn)證過程1 的情況一樣。
正常調(diào)用 [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES]; 是會觸發(fā)監(jiān)聽, 唯獨(dú)那個視頻界面,沒有觸發(fā)監(jiān)聽的情況下,正常顯示小圈圈。
所以, 視頻界面里顯示的小圈圈,肯定不是通過常規(guī)調(diào)用 setNetworkActivityIndicatorVisible 方法顯示出來的。
更新猜想: 第三方庫引發(fā)的問題,并且不是通過常規(guī)方法調(diào)用
驗(yàn)證過程3
顯示小圈圈的情況下,分析了該界面的視圖層級,發(fā)現(xiàn)在 statusBar 上,有 類型為UIActivityIndicatorView的視圖存在(并且怪異的存在了兩個)。
那正常情況下,通過 [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES]; 顯示小圈圈時,視圖層級是如何的呢? 通過分析驗(yàn)證, 也是一樣的。
層級都是 UIStatusBarView -> UIStatusBarForegroundView -> UIStatusBarActivityItemView -> UIActivityIndicatorView
想到解決方案:
既然小圈圈都是 UIActivityIndicatorView 類型的視圖,而 UIActivityIndicatorView 開始動畫常規(guī)都是調(diào)用 startAnimation 方法。
那何不使用黑魔法(method swizzling)來重寫它的 startAnimation 方法,
判斷它的superView是否為 “UIStatusBarActivityItemView”類型,如果是,則直接跳出。否則,執(zhí)行原有的 startAnimation方法。
Talk is cheap. Show me the code.
以下是 .m 文件的代碼
@implementation UIActivityIndicatorView (HideNetworkActivityIndicator)+ (void)load {static dispatch_once_t onceToken;dispatch_once(&onceToken, ^{Class class = [self class];SEL originalSelector = @selector(startAnimating);SEL swizzledSelector = @selector(xxx_startAnimating);Method originalMethod = class_getInstanceMethod(class, originalSelector);Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);// When swizzling a class method, use the following:// Class class = object_getClass((id)self);// ...// Method originalMethod = class_getClassMethod(class, originalSelector);// Method swizzledMethod = class_getClassMethod(class, swizzledSelector);BOOL didAddMethod =class_addMethod(class,originalSelector,method_getImplementation(swizzledMethod),method_getTypeEncoding(swizzledMethod));if (didAddMethod) {class_replaceMethod(class,swizzledSelector,method_getImplementation(originalMethod),method_getTypeEncoding(originalMethod));} else {method_exchangeImplementations(originalMethod, swizzledMethod);}}); }#pragma mark - Method Swizzling- (void)xxx_startAnimating{if (self.superview != nil && [NSStringFromClass([self.superview class]) isEqualToString: @"UIStatusBarActivityItemView"]) {NSLog(@"黑魔法禁止?fàn)顟B(tài)欄的loading顯示: %@", self);} else {[self xxx_startAnimating];}}@end成功了!!!
(在xxx_startAnimation方法體內(nèi)打斷點(diǎn),程序進(jìn)入視頻播放界面,觸發(fā)斷點(diǎn),看調(diào)用棧,果然是第三方庫引發(fā)的問題。)
參考資料:https://nshipster.cn/method-s...
總結(jié)
以上是生活随笔為你收集整理的黑魔法(method-swizzling)解决第三方库引发的问题的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 老公梦到蜈蚣是胎梦吗
- 下一篇: 没怀孕做梦梦到怀孕流产什么预兆吗