「 iOS 」NSProxy

Objective-C做爲一種動態消息型語言,其機制不一樣於Java,C#等編譯型語言.
它將數據類型的肯定等工做推遲到了運行時期來執行,而且它調用方法的方式實質是像對象發送消息,根據selector在對象的本類以及父類中的方法列表進行查找,若是都找不到就會啓動消息轉發機制.atom

回到正題,這個話題我想談下OC的單繼承原則.
OC確實是只能單繼承的語言,可是基於運行時的機制,卻有一種方法讓它來實現一下"僞多繼承".就是利用NSProxy這個類.spa

NSProxy是和NSObject同級的一個類,能夠說它是一個虛擬類,它只是實現了<NSObject>的協議.它的做用有點相似於一個複製類,有人曾經笑談它是複製操做,想一想其實也挺貼切的,其實原理確實如此.code

工做原理:
用一個繼承於NSProxy的子類,在它內部實現一些方法,暴露一個公開方法transform,這個方法是使它變身的關鍵.而後它變身以後能夠對那些對象發送消息,而且能夠在內部攔截消息的內容並修改.

能夠說,NSProxy幾乎能夠變身成爲任何對象.orm

//JanProxy.h

#import <Foundation/Foundation.h>
@interface JanProxy : NSProxy
- (void)transformObjc:(NSObject *)objc;
@end
//JanProxy.m

#import "JanProxy.h"
@interface JanProxy ()
@property(nonatomic,strong)NSObject *objc;
@end
@implementation JanProxy

- (void)transformObjc:(NSObject *)objc
{
    //複製對象
    self.objc = objc;
}

//2.有了方法簽名以後就會調用方法實現
- (void)forwardInvocation:(NSInvocation *)invocation
{
    if (self.objc) {
        //攔截方法的執行者爲複製的對象
        [invocation setTarget:self.objc];
           
        if ([self.objc isKindOfClass:[NSClassFromString(@"Cat") class]]) {
            //攔截參數 Argument:表示的是方法的參數  index:表示的是方法參數的下標
            NSString *str = @"攔截消息";
            [invocation setArgument:&str atIndex:2];
        }
        
        //開始調用方法
        [invocation invoke];
    }
    
}

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

@end

使用方法對象

Dog *dog = [[Dog alloc]init];
    //OC中方法的調用本質上是給這個對象發送一個消息
    Cat *cat = [[Cat alloc] init];
    //開始複製攔截方法
    JanProxy *proxy = [JanProxy alloc];
    //開始變身成貓
    [proxy transformObjc:cat];
    //開始調貓的方法
    [proxy performSelector:@selector(eat:) withObject:@"貓發出消息"];
    
    //開始變身成狗
    [proxy transformObjc:Dog];
    //開始調用學生的方法
    [proxy performSelector:@selector(shut)];

最後的結果繼承

控制檯輸出結果

發現沒有,貓發出消息已經被子類的內部攔截而且作出了修改.rem

總結

OC中存在這麼一個默默無聞的類NSProxy,填補了"多繼承"這個空白區.get

相關文章
相關標籤/搜索