12

NSProxy类参考是这样说的:

通常,发往代理的消息被转发到真实对象或使代理加载(或将其自身转换为)真实对象。

“将自己转化为真实对象”究竟是如何工作的?

为了让事情更具体一点,假设类Foo有一个方法,该方法newFooWithString:接受一个字符串并返回一个新的Foo. 是否可以设置一个NSProxy坐在那里,如果pleaseBecomeAFooUsingString: @"bar"收到一条消息,将自己转换为[Foo newFooWithString: @"bar"],占用相同的内存,而不会弄乱可能存在的其他对自身的引用?

4

2 回答 2

6

如果您在整个代码中都有一个指向同一个 NSProxy 实例的指针并且将“转换”它,那么它将在整个代码中发生变化。无法区分对象的方法调用者,因此您将无法在代码中自动替换目标以转发方法调用。常见的可转换代理将如下所示:

MyTrickyProxy.h

#import <Foundation/Foundation.h>

@interface MyTrickyProxy : NSProxy {
    NSObject *object;
}

- (id)transformToObject:(NSObject *)anObject;

@end

MyTrickyProxy.m

#import "MyTrickyProxy.h"

@implementation MyTrickyProxy

- (void)dealloc 
{
    [object release];
    object = nil;

    [super dealloc];
}

- (NSString *)description 
{
    return [object description];
}

//Stupid transform implementation just by assigning a passed in object as transformation target. You can write your factory here and use passed in object as id for object that need ot be created.
- (id)transformToObject:(NSObject *)anObject 
{
    if(object != anObject) {
        [object release];
    }
    object = [anObject retain];

    return object;
}

- (void)forwardInvocation:(NSInvocation *)invocation 
{
    if (object != nil) {
        [invocation setTarget:object];    
        [invocation invoke];
    }
}

- (NSMethodSignature *)methodSignatureForSelector:(SEL)sel 
{
    NSMethodSignature *result;
    if (object != nil) {
        result = [object methodSignatureForSelector:sel];
    } else {
        //Will throw an exception as default implementation
        result = [super methodSignatureForSelector:sel];
    }

    return result;
}

@end

所以你要求的是某种代码魔法,但是 NSProxy 是一个简单的消息转发器,根本没有任何魔法,所以你的目标无法以你描述的方式实现。

于 2011-08-07T02:56:22.800 回答
0

您可以创建 NSProxy 的子类,根据您想要的每个标准更改它转发它的方法的对象。因此,您的对象将始终指向 NSProxy,但您 pleaseBecomeAFooUsingString: 会将其转发到的对象更改为 Foo。

于 2011-08-07T22:32:41.550 回答