ISA Swizzling 《iOS程式設計實戰》

Channnnne發表於2018-01-25

《iOS程式設計實戰》24.6節 方法混寫和ISA混寫的區別 KVO是通過ISA混寫實現的,這樣系統框架就可以在我們的類中注入通知程式碼,一如把程式碼注入系統框架。 ISA混寫是修改某一個特定物件的類,不會影響這個類的其他物件。 修改物件的類為自定義的類後,自定義類中的方法就能執行,我們可以在這些方法中新增我們想要的功能。當然,這些方法都存在於修改前的類中,所以自定義類都是修改前類的子類。

NSObject+SetClass.h

#import <Foundation/Foundation.h>
@interface NSObject (SetClass)
- (void)setClass:(Class)aClass;
@end
複製程式碼

NSObject+SetClass.m

#import "NSObject+SetClass.h"
#import <objc/runtime.h>
@implementation NSObject (SetClass)
- (void)setClass:(Class)aClass {
    //確保兩個類大小一樣,也就是說aClass不能宣告任何 ivar 或者合成屬性 
    NSAssert(class_getInstanceSize([self class]) == class_getInstanceSize(aClass), @"Classes must be the same size to swizzle.");

    //設定一個物件的類,這裡改變 self 的類為 aClass
    //Class object_setClass(id object, Class cls)
    object_setClass(self, aClass);}
@end
複製程式碼

MYNotificationCenter.h

#import <Foundation/Foundation.h>
@interface MYNotificationCenter : NSNotificationCenter    
// 這裡絕對不要定義任何例項變數 ivar 或者合成屬性
@end
複製程式碼

MYNotificationCenter.m

#import "MYNotificationCenter.h"
@implementation MYNotificationCenter

- (void)addObserver:(id)observer selector:(SEL)aSelector name:(NSString *)aName object:(id)anObject
{
   // 新增的程式碼
    NSLog(@"Adding observer: %@", observer);
   //  呼叫自定義類的父類方法,保證原來功能不缺失
   [super addObserver:observer selector:aSelector name:aName
                object:anObject];}
@end
複製程式碼

在程式開始的某個地方執行方法混寫:

#import "NSObject+SetClass.h"
#import "MYNotificationCenter.h"

NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
[center setClass:[MYNotificationCenter class]];
//之後,呼叫系統[NSNotificationCenter defaultCenter]時會自動替換會自定義的[MYNotificationCenter defaultCenter]

複製程式碼

相關文章