iOS Class 使用NSProxy和NSObject設計代理類的差異,nsproxynsobject

來源:互聯網
上載者:User

iOS Class 使用NSProxy和NSObject設計代理類的差異,nsproxynsobject

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

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

繼承自NSProxy

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@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.經測試發現以下兩個在<NSObject>中定義的介面, 在二者之間表現是不一致的:

1
2
3
4
5
6
7
8
9
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
2
1 0
1 0

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

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

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

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

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

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

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.