iOS 클래스는 NSProxy와 NSObject를 사용하여 프록시 클래스의 차이를 설계합니다.

메시지 전달을 사용해야하는 프록시 클래스를 만들 때 프로그래머마다 사용 방법이 다릅니다. 일부는 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>接口中定义的部分方法), 所以其它方法都能够按照设计的预期被转发到被代理的对象中.

추천

출처blog.csdn.net/wangletiancsdn/article/details/98042488