如果你還不知道什么是Method Swizzling,你可以看看NSHipster 的文章 ,我簡單介紹一下,method swizzling 可以看成劫持了一個方法。
在下冶等地區,都構建了全面的區域性戰略布局,加強發展的系統性、市場前瞻性、產品創新能力,以專注、極致的服務理念,為客戶提供成都網站制作、網站建設 網站設計制作定制網站建設,公司網站建設,企業網站建設,成都品牌網站建設,成都全網營銷,成都外貿網站建設,下冶網站建設費用合理。
我們可以看看NSHipster 的文章中有以下代碼:
- (void)xxx_viewWillAppear:(BOOL)animated {
[self xxx_viewWillAppear:animated];
NSLog(@"viewWillAppear: %@", self);
}
是不是覺得遞歸無限循環,事實上并不會,你可以這么理解,一個具體的SEL是個名字,一個具體的IMP是個函數指針,在類里面它們是靠一個表建立聯系。
假設(純屬虛構) UIViewController 的 @selector(viewWillAppear:) 對應的內部實現為以下
void _UIKIT_Internal_UIViewController_viewWillAppear(id vc, SEL selector, BOOL animated) {
...// ^_^蘋果私有代碼
}
假設UIViewController 的 @selector(xxx_viewWillAppear:) 的實現為以下
void my_xxx_viewWillAppear(id vc, SEL selector, BOOL animated) {
[vc performSelector:@selector(xxx_viewWillAppear) withObject:@(animated)];
NSLog(@"viewWillAppear: %@", vc);
}
那么未替換方法前@selector(viewWillAppear:)對應的指針就是&_UIKIT_Internal_UIViewController_viewWillAppear
那么未替換方法前@selector(xxx_viewWillAppear:)對應的指針就是&my_xxx_viewWillAppear
一旦替換方法后,@selector(viewWillAppear:)對應的指針就是&my_xxx_viewWillAppear,
@selector(xxx_viewWillAppear:)對應的指針就是&_UIKIT_Internal_UIViewController_viewWillAppear
my_xxx_viewWillAppear 中的 [vc performSelector:@selector(xxx_viewWillAppear) withObject:@(animated)];
相當于什么,相當于 調用@selector(xxx_viewWillAppear:)所指的函數&_UIKIT_Internal_UIViewController_viewWillAppear, 也就是相當于調用原來的函數,所以這并不是遞歸。
@implementation UIViewController (Tracking)
+ (void)load {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
[self replaceOriginalSelector:@selector(viewWillAppear:) withNewSelector:@selector(xxx_viewWillAppear:)];
});
}
- (void)xxx_viewWillAppear:(BOOL)animated {
[self xxx_viewWillAppear:animated];
NSLog(@"x_viewWillAppear: %@", self);
}
@end
@interface ViewController ()
@end
@implementation ViewController
+ (void)load {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
[self replaceOriginalSelector:@selector(viewWillAppear:) withNewSelector:@selector(yyy_viewWillAppear:)];
});
}
- (void)yyy_viewWillAppear:(BOOL)animated {
[self yyy_viewWillAppear:animated];
NSLog(@"y_viewWillAppear: %@", self);
}
@end
3.也是順序問題
以下,來自另一篇文章defagos.github.io
它是這么說的,NSObject 實現了 -awakeFromNib,但是它的子類UIView,孫類UILabel都沒有在本類實現- awakeFromNib,那么替換時如果不寫在category +(void) load方法里,那么順序也是個問題
假設我們先替換了UILabel的- awakeFromNib方法,然后再替換了UIView的- awakeFromNib,那么UILabel的- awakeFromNib方法就不會執行UIView的- awakeFromNib方法,因為它們都是獨立替換的是NSObject方法,這篇文章defagos.github.io 提供了一個解決方案,當本類沒有實現方法(如 UILabel -awakeFromNib)時,首先先添加一個block方法 調用[super awakeFromNib];,我初次看到也是覺得這個方式很好,但是我發現兩點不足,
在構建objc_super時,如果父類本身沒有實現方法,.super_class = class_getSuperclass(clazz),這么寫好像是沒有用的,似乎super_class要填真正實現方法的祖先類,而不能一概的寫class_getSuperclass
struct objc_super super = {
.receiver = self,
.super_class = class_getSuperclass(clazz)
};
id (*objc_msgSendSuper_typed)(struct objc_super *, SEL, va_list) = (void *)&objc_msgSendSuper;
由于 va_list 變量最后是靠宏 va_arg(ap, type)
來獲取的,type又是未知的,這個函數指針的強制轉換轉換可能會出現問題
可見,Swizzling正確的順序是十分重要的,(共同點:類本身沒有真正實現方法)
- (void)awakeFromNib {
[super awakeFromNib];
}
新聞標題:iOS開發:MethodSwizzling
網頁路徑:http://m.newbst.com/article4/gdeooe.html
成都網站建設公司_創新互聯,為您提供云服務器、靜態網站、做網站、網站收錄、網站營銷、企業網站制作
聲明:本網站發布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創新互聯