iOSクラスはNSProxyとNSObjectを使用してプロキシクラスの違いを設計します

メッセージ転送を使用する必要のあるプロキシクラスを作成する場合、プログラマーによって使用方法が異なることがよくあります。NSObjectからの継承を使用するものと、NSProxyからの継承を使用するものがあります。どちらもFoundationフレームワークの基本クラスです。そして、それらはすべて<NSObject>このインターフェースを実装しています。命名とドキュメントから、NSProxyはこれを行うために生まれました。しかし、それでも、それらはすべて同じメッセージ転送インターフェースを定義しているので、両方を使用してこの作業を完了すると違いは何ですか?

最初に、2つを介してプロキシクラスを作成するための最も基本的な実装コードを投稿します。

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; 
    自己を返す; 
} 

-(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; 
    }
    自己を返す; 
} 

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

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

@end

初期化の仕様の詳細な違いを除いて、コードは基本的に同じです。この違いは、NSProxyの基本クラスがデフォルトのinitメソッドを定義していないためです。

1.テストの結果、で<NSObject>定義されている次の2つのインターフェイスが2つの間で矛盾していることがわかりました

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 responsesToSelector:@selector(length)]); 
NSLog(@ "%d"、[proxyB responsesToSelector:@selector(length)]); 

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

結果は異なる結論を出力します:

1 
2
1 0 
1 0

つまり、NSObjectから継承されたプロキシクラスは、2つのメソッド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>接口中定义的部分方法), 所以其它方法都能够按照设计的预期被转发到被代理的对象中.

おすすめ

転載: blog.csdn.net/wangletiancsdn/article/details/98042488