国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

Method Swizzling中的陷阱

2019-11-09 18:15:10
字體:
來源:轉載
供稿:網友

作者:代培 地址:http://blog.csdn.net/dp948080952/article/details/54882811 轉載請注明出處

這篇文章不是介紹什么是方法交換,這類文章很多,如果你不知道什么是方法交換可以看這篇文章:Method Swizzling

陷阱

方法交換是很危險的東西,會產生一些未知的錯誤,最近在使用方法交換時就遇到了這樣的問題,在我交換了一個系統方法后,在調用這個方法時會在我交換的方法中循環無法跳出。

最終我找到了問題的關鍵,那就是這個方法可能不存在!

每次iOS版本的更新都會出現一些新的API,這些API在之前的版本中就不存在,而你在交換一個方法時如果不考慮它是否存在,那就會導致嚴重的錯誤。

比如我曾經交換過一個方法:

- (void)openURL:(NSURL*)url options:(NSDictionary<NSString *, id> *)options completionHandler:(void (^ __nullable)(BOOL success))completion

這個方法只在iOS10之后有,別人在使用的時候也會先判斷這個方法是否會被響應,但是我們看下面的交換代碼會先添加這個方法,如果這個方法不存在,那么本來不會響應就變成了會響應,那么在iOS10之前的系統就會進入這個方法,導致死循環。

Class class = [self class]; Method method1 = class_getInstanceMethod(class, sel1); Method method2 = class_getInstanceMethod(class, sel2); BOOL didAddMethod = class_addMethod(class, sel1, method_getImplementation(method2), method_getTypeEncoding(method2)); if (didAddMethod) { class_replaceMethod(class, sel2, method_getImplementation(method1), method_getTypeEncoding(method1)); } else { method_exchangeImplementations(method1, method2); }

解決方案

解決這個問題也很簡單就是交換前做一個判斷:

if (![class instancesRespondToSelector:sel1] || ![class instancesRespondToSelector:sel2]) { return ; }

如果不響應這個方法,直接返回。

封裝

為了不重復寫方法交換的代碼,也能減少錯誤,我們可以將其封裝,將其放在NSObject的Category中再合適不過了。

NSObject+DPExtension.h

#import <Foundation/Foundation.h>@interface NSObject (DPExtension)+ (void)intanceMethodExchangeWithOriginSelector:(SEL)sel1 swizzledSelector:(SEL)sel2;@end

NSObject+DPExtension.m

#import "NSObject+DPExtension.h"#import <objc/runtime.h>@implementation NSObject (DPExtension)+ (void)intanceMethodExchangeWithOriginSelector:(SEL)sel1 swizzledSelector:(SEL)sel2 { Class class = [self class]; if (![class instancesRespondToSelector:sel1] || ![class instancesRespondToSelector:sel2]) { return ; } Method method1 = class_getInstanceMethod(class, sel1); Method method2 = class_getInstanceMethod(class, sel2); BOOL didAddMethod = class_addMethod(class, sel1, method_getImplementation(method2), method_getTypeEncoding(method2)); if (didAddMethod) { class_replaceMethod(class, sel2, method_getImplementation(method1), method_getTypeEncoding(method1)); } else { method_exchangeImplementations(method1, method2); }}@end

就是這些^_^


上一篇:第十一章粒子系統

下一篇:APP數據備份

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 黔西| 改则县| 兴宁市| 阳曲县| 辰溪县| 新绛县| 米脂县| 杭州市| 林州市| 确山县| 溆浦县| 淮北市| 嘉善县| 勃利县| 巴林右旗| 紫金县| 湖州市| 江安县| 呼玛县| 隆化县| 翁牛特旗| 盐城市| 彩票| 靖边县| 丰宁| 稻城县| 灵石县| 齐齐哈尔市| 来凤县| 辽宁省| 凤凰县| 彭山县| 平湖市| 新和县| 民县| 通州市| 纳雍县| 大港区| 大余县| 长宁县| 云梦县|