天天看點

Method Swizzling的應用

Runtime消息轉發雖然功能強大,但需要我們了解并且能更改對應類的源代碼,因為我們需要實作自己的轉發邏輯。當我們無法觸碰到某個類的源代碼,卻想更改這個類某個方法的實作時,該怎麼辦呢?可能繼承類并重寫方法是一種想法,但是有時無法達到目的。這裡介紹的是 Method Swizzling ,它通過重新映射方法對應的實作來達到“偷天換日”的目的。跟消息轉發相比,Method Swizzling 的做法更為隐蔽,甚至有些冒險,也增大了debug的難度。下面我們來了解一下Method Swizzling 的具體應用。

使用Method Swizzling 一鍵修改字型

+(void)load{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        SEL systemSel = @selector(willMoveToSuperview:);
        SEL swizzlSel = @selector(swizzl_willMoveToSuperview:);

        Method sysMethod = class_getInstanceMethod([self class], systemSel);
        Method swizzlMethod = class_getInstanceMethod([self class], swizzlSel);
        //将系統方法 的IMP轉換為自定義的方法的IMP,如果自定義的方法的IMP沒有實作,那麼就會傳回YES。
        BOOL isAdd = class_addMethod(self, systemSel, method_getImplementation(swizzlMethod), method_getTypeEncoding(swizzlMethod));
        if (isAdd) {
            class_replaceMethod(self, swizzlSel, method_getImplementation(sysMethod), method_getTypeEncoding(sysMethod));
        }else{
            method_exchangeImplementations(sysMethod, swizzlMethod);
        }
    });
}
- (void)swizzl_willMoveToSuperview:(UIView *)newSuperView{
    //這一步也很關鍵,是必須要調用的,因為這一步回去執行系統的方法對應的iMP,因為切換了。多以我們可以通過這方式來擴充系統方法。
    [self swizzl_willMoveToSuperview:newSuperView];
      if ([self isKindOfClass:NSClassFromString(@"UIButtonLabel")]) {
          self.backgroundColor = [UIColor redColor];
      }
    self.font = [UIFont fontWithName:SCRIPT_NAME size:self.font.pointSize];

}
           

使用同樣的原理,我們可以對系統的方法進行拓展。

繼續閱讀