Objective-C中的複製忍者卡卡西---NSProxy

是否是曾經在別人面前誇下海口:Objective-C中全部的類的基類都是NSObject;我以前也一直也這麼覺得的,可是認真看了下官方文檔:java

啪啪,好響,好疼~(看來英文水平也很重要啊......) 不賣關子了,咱們今天要討論的就是NSProxy。它是跟NSObject屬於同一級別的類,是個抽象類,只是實現了<NSObject>的協議;編程

按照官方的定義:NSProxy是一個爲對象定義接口的抽象父類,而且爲其它對象或者一些不存在的對象扮演了替身角色。一般,給proxy的消息被轉發給實際對象或者致使proxy加載(轉化它爲)實際對象。NSProxy的子類能被用來實現透明的分佈式消息(例如:NSDistantObject)或者延緩要花費昂貴代價建立的對象的實現。app

下面咱們看看NSProxy是怎麼複製別的類(幾乎全部類)的:分佈式

咱們先建立一個類繼承自NSProxy:學習

#import "KakashiProxy.h"

@interface KakashiProxy ()

@property(nonatomic,strong)NSObject *objc;

@end

@implementation KakashiProxy

- (void)changeObj:(NSObject *)obj {
    
    self.objc = obj;
    
}

//方法簽名
- (NSMethodSignature *)methodSignatureForSelector:(SEL)sel {
    
    NSMethodSignature *signature = nil;
    if ([self.objc methodSignatureForSelector:sel]) {
        signature = [self.objc methodSignatureForSelector:sel];
    }else {
        signature = [super methodSignatureForSelector:sel];
    }
    
    return signature;
}

//調用方法實現
- (void)forwardInvocation:(NSInvocation *)invocation {
    
    if ([self.objc respondsToSelector:invocation.selector]) {
        NSString *selName = NSStringFromSelector(invocation.selector);
        NSLog(@"selector name : %@",selName);
        //這裏咱們能夠作一些邏輯處理,好比埋點統計之類的
        [invocation invokeWithTarget:self.objc];
    }else {
        [super forwardInvocation:invocation];
    }
    
}

@end
複製代碼

能夠看到咱們重寫了兩個方法:methodSignatureForSelector:forwardInvocation:(NSInvocation *)invocation,前者是實現方法簽名的,咱們能夠在這個方法中,直接將咱們複製的對象進行方法簽名,而後生成NSInvocation。接着方法forwardInvocation會被調用,在這個方法中,咱們直接將invacationtarget設置爲咱們複製的對象。在這個方法中咱們能夠作一點事情,好比根據類名作一些邏輯,也能夠作一些數據埋點之類的。 而後咱們看看怎麼使用這個複製忍者的: 咱們隨便定義兩個類,併爲每一個類設置了一個方法:atom

Parker-Dog.hspa

#import "Parker-Dog.h"
    
    @implementation Parker_Dog
    
    - (void)bite {
        NSLog(@"卡卡西召喚通靈獸Paker並咬住了再不斬!");
    }
    
    @end
複製代碼

Wood.h3d

#import "Wood.h"

    @implementation Wood
    
    - (void)boom{
    
        NSLog(@"變!木頭!...");
        
    }
複製代碼

調用:code

//初始化一個木頭
    Wood *wood = [[Wood alloc] init];
    //初始化一個帕克
    Parker_Dog  *paker = [[Parker_Dog alloc] init];
    //初始化一個卡卡西
    KakashiProxy *proxy = [KakashiProxy alloc];
    
    //變木頭
    [proxy changeObj:wood];
    //調用木頭的方法
    [proxy performSelector:@selector(boom) withObject:nil];
    
    //變帕克
    [proxy changeObj:paker];
    //調用帕克的方法
    [proxy performSelector:@selector(bite) withObject:nil];
複製代碼

控制檯輸出: orm

這樣,咱們經過proxy這個類實現了複製woodpaker,能夠分別調用各個類的方法了。

總結

其實也不能叫複製吧,你們也能夠看到,這個實現其實就是利用了runtime的消息轉發機制。這篇文章就算是對NSProxy的一個簡單認識吧,還有些NSProxy的高級用法可能筆者尚未學習到,還要繼續努力,有時間須要深刻研究下這個特殊的類。

參看文章

相關文章
相關標籤/搜索