메시지 전달을 사용해야하는 프록시 클래스를 만들 때 프로그래머마다 사용 방법이 다릅니다. 일부는 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 (비 원자, 강력한) id 대상; @end @implementation THProxyA- (id) initWithObject : (id) object { self.target = object; 자기 반환; } -(NSMethodSignature *) methodSignatureForSelector : (SEL) selector { return [self.target methodSignatureForSelector : selector]; } -(무효) 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 (비원 자성 , 강력한) 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]; } -(무효) forwardInvocation : (NSInvocation *) invocation { [invocation invokeWithTarget : self.target]; } @end |
초기화 사양의 세부적인 차이점을 제외하면 코드는 기본적으로 동일하며 NSProxy의 기본 클래스는 기본 init 메소드를 정의하지 않기 때문입니다.
1. 테스트 후에 <NSObject>
정의 된 다음 두 인터페이스가 둘간에 일치하지 않는 것으로 확인되었습니다.
1 2 3 4 5 6 7 8 9 |
NSString * string = @ "테스트"; THProxyA * proxyA = [[THProxyA 할당] initWithObject : string]; THProxyB * proxyB = [[THProxyB 할당] 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>
接口中定义的部分方法), 所以其它方法都能够按照设计的预期被转发到被代理的对象中.