你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發基礎 >> 使用NSProxy和NSObject設計代理類的差異

使用NSProxy和NSObject設計代理類的差異

編輯:IOS開發基礎

經常發現在一些需要使用消息轉發而創建代理類時, 不同的程序員都有著不同的使用方法, 有些采用繼承於NSObject, 而有一些采用繼承自NSProxy. 二者都是Foundation框架中的基類, 並且都實現了這個接口, 從命名和文檔中看NSProxy天生就是用來干這個事情的. 但即便如此, 它們卻都定義了相同的消息轉發的接口, 那我們在使用二者來完成這個工作時有什麼差異呢.

先貼一下通過二者來創建代理類的最基本實現代碼.

繼承自NSProxy

@interface THProxyA : NSProxy

@property (nonatomic, strong) id target;

@end

@implementation THProxyA

- (id)initWithObject:(id)object {

    self.target = object;
    
    return self;
}
- (NSMethodSignature *)methodSignatureForSelector:(SEL)selector {

    return [self.target methodSignatureForSelector:selector];
    
}
- (void)forwardInvocation:(NSInvocation *)invocation {

    [invocation invokeWithTarget:self.target];
    
}

@end

繼承自NSObject

@interface THProxyB : NSObject

@property (nonatomic, strong) id target;

@end

@implementation THProxyB

- (id)initWithObject:(id)object {

    self = [super init];
    
    if (self) {
    
        self.target = object;
    }
    
    return self;
}

- (NSMethodSignature *)methodSignatureForSelector:(SEL)selector {

    return [self.target methodSignatureForSelector:selector];
    
}
- (void)forwardInvocation:(NSInvocation *)invocation {

    [invocation invokeWithTarget:self.target];
    
}

@end

代碼基本是一致的, 除了初始化時規范的寫法有細節差異, 這個差異是因為NSProxy這個基類沒有定義默認的init方法.

1.經測試發現以下兩個在中定義的接口, 在二者之間表現是不一致的:

NSString *string = @"test";

THProxyA *proxyA = [[THProxyA alloc] initWithObject:string];

THProxyB *proxyB = [[THProxyB alloc] initWithObject:string];

NSLog(@"%d", [proxyA respondsToSelector:@selector(length)]);

NSLog(@"%d", [proxyB respondsToSelector:@selector(length)]);

NSLog(@"%d", [proxyA isKindOfClass:[NSString class]]);

NSLog(@"%d", [proxyB isKindOfClass:[NSString class]]);

結果會輸出完成不同的結論:

1 0
1 0

也就是說通過繼承自NSObject的代理類是不會自動轉發respondsToSelector:和isKindOfClass:這兩個方法的, 而繼承自NSProxy的代理類卻是可以的. 測試中定義的其它接口二者表現都是一致的.

2.NSObject的所有Category中定義的方法無法在THProxyB中完成轉發

舉一個很常見的例子, valueForKey:是定義在NSKeyValueCoding這個NSObject的Category中的方法, 嘗試二者執行的表現.

NSLog(@"%@",[proxyA valueForKey:@"length"]);

NSLog(@"%@",[proxyB valueForKey:@"length"]);

這段代碼第一句能正確運行, 但第二行卻會拋出異常, 分析最終原因其實很簡單, 因為valueForKey:是NSObject的Category中定義的方法, 讓NSObject具備了這樣的接口, 而消息轉發是只有當接收者無法處理時才會通過forwardInvocation:來尋求能夠處理的對象.

3.結論: 如此看來NSProxy確實更適合實現做為消息轉發的代理類, 因為作為一個抽象類, NSProxy自身能夠處理的方法極小(僅接口中定義的部分方法), 所以其它方法都能夠按照設計的預期被轉發到被代理的對象中.


  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved