真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

iOS開發(fā):MethodSwizzling-創(chuàng)新互聯(lián)

iOS 開發(fā)之Method Swizzling

前言

如果你還不知道什么是Method Swizzling,你可以看看NSHipster 的文章 ,我簡單介紹一下,method swizzling 可以看成劫持了一個方法。

目前創(chuàng)新互聯(lián)已為近千家的企業(yè)提供了網(wǎng)站建設(shè)、域名、網(wǎng)頁空間、網(wǎng)站運營、企業(yè)網(wǎng)站設(shè)計、淮陰網(wǎng)站維護等服務(wù),公司將堅持客戶導(dǎo)向、應(yīng)用為本的策略,正道將秉承"和諧、參與、激情"的文化,與客戶和合作伙伴齊心協(xié)力一起成長,共同發(fā)展。

我們可以看看NSHipster 的文章中有以下代碼:

- (void)xxx_viewWillAppear:(BOOL)animated {
    [self xxx_viewWillAppear:animated];
    NSLog(@"viewWillAppear: %@", self);
}

是不是覺得遞歸無限循環(huán),事實上并不會,你可以這么理解,一個具體的SEL是個名字,一個具體的IMP是個函數(shù)指針,在類里面它們是靠一個表建立聯(lián)系。


假設(shè)(純屬虛構(gòu)) UIViewController 的 @selector(viewWillAppear:) 對應(yīng)的內(nèi)部實現(xiàn)為以下

void _UIKIT_Internal_UIViewController_viewWillAppear(id vc, SEL selector, BOOL animated) {
  ...// ^_^蘋果私有代碼
}

假設(shè)UIViewController 的 @selector(xxx_viewWillAppear:) 的實現(xiàn)為以下

void my_xxx_viewWillAppear(id vc, SEL selector, BOOL animated) {
  [vc performSelector:@selector(xxx_viewWillAppear) withObject:@(animated)];  
  NSLog(@"viewWillAppear: %@", vc);
}

那么未替換方法前@selector(viewWillAppear:)對應(yīng)的指針就是&_UIKIT_Internal_UIViewController_viewWillAppear

那么未替換方法前@selector(xxx_viewWillAppear:)對應(yīng)的指針就是&my_xxx_viewWillAppear


一旦替換方法后,@selector(viewWillAppear:)對應(yīng)的指針就是&my_xxx_viewWillAppear,
@selector(xxx_viewWillAppear:)對應(yīng)的指針就是&_UIKIT_Internal_UIViewController_viewWillAppear


my_xxx_viewWillAppear 中的 [vc performSelector:@selector(xxx_viewWillAppear) withObject:@(animated)];
相當于什么,相當于 調(diào)用@selector(xxx_viewWillAppear:)所指的函數(shù)&_UIKIT_Internal_UIViewController_viewWillAppear, 也就是相當于調(diào)用原來的函數(shù),所以這并不是遞歸。


存在的危險

  1. 有些NSObject類是類簇,替換方法要找到真正的類,如NSArray替換方法,通常用'_NSArrayM'或'_NSArrayI'
  2. 執(zhí)行順序問題,ViewController是自己寫的類,ViewController的load方法和UIViewController的category里的load方法哪個先執(zhí)行,如果是ViewController的先執(zhí)行,那么UIViewController的swizzling就對ViewController無效,如果ViewController的后執(zhí)行就一切正常,代碼如下
@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 實現(xiàn)了 -awakeFromNib,但是它的子類UIView,孫類UILabel都沒有在本類實現(xiàn)- awakeFromNib,那么替換時如果不寫在category +(void) load方法里,那么順序也是個問題

假設(shè)我們先替換了UILabel的- awakeFromNib方法,然后再替換了UIView的- awakeFromNib,那么UILabel的- awakeFromNib方法就不會執(zhí)行UIView的- awakeFromNib方法,因為它們都是獨立替換的是NSObject方法,這篇文章defagos.github.io 提供了一個解決方案,當本類沒有實現(xiàn)方法(如 UILabel -awakeFromNib)時,首先先添加一個block方法 調(diào)用[super awakeFromNib];,我初次看到也是覺得這個方式很好,但是我發(fā)現(xiàn)兩點不足,

  1. 在構(gòu)建objc_super時,如果父類本身沒有實現(xiàn)方法,.super_class = class_getSuperclass(clazz),這么寫好像是沒有用的,似乎super_class要填真正實現(xiàn)方法的祖先類,而不能一概的寫class_getSuperclass

    struct objc_super super = {
            .receiver = self,
            .super_class = class_getSuperclass(clazz)
        };
  2. va_list的使用
id (*objc_msgSendSuper_typed)(struct objc_super *, SEL, va_list) = (void *)&objc_msgSendSuper;

由于 va_list 變量最后是靠宏 va_arg(ap, type) 來獲取的,type又是未知的,這個函數(shù)指針的強制轉(zhuǎn)換轉(zhuǎn)換可能會出現(xiàn)問題


結(jié)語

可見,Swizzling正確的順序是十分重要的,(共同點:類本身沒有真正實現(xiàn)方法)

  • 如果你的Swizzling是靜態(tài)的,那么就保證父類的Swizzling發(fā)生在子類的Swizzling前
  • 如果你的Swizzling是動態(tài)的或者你管不好他們先后順序,那么就要用defagos的方法動態(tài)的call objc_msgSendSuper,
  • 或許你勤快一點還可以直接在category里面重寫,
    - (void)awakeFromNib {
    [super awakeFromNib];
    }

另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)cdcxhl.cn,海內(nèi)外云服務(wù)器15元起步,三天無理由+7*72小時售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國服務(wù)器、虛擬主機、免備案服務(wù)器”等云主機租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡單易用、服務(wù)可用性高、性價比高”等特點與優(yōu)勢,專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場景需求。


當前題目:iOS開發(fā):MethodSwizzling-創(chuàng)新互聯(lián)
文章網(wǎng)址:http://weahome.cn/article/csccjh.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部