NSProxy如何“将自己转化为另一个对象”?

时间:2011-08-07 01:55:11

标签: objective-c cocoa cocoa-touch nsproxy

NSProxy Class Reference说:

  

通常,将代理的消息转发给真实对象,或者使代理加载(或转换为真实对象)。

“将自身转化为真实对象”究竟会如何运作?

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

2 个答案:

答案 0 :(得分: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是一个简单的消息转发器,根本没有任何魔法,所以你的目标无法按照你所描述的方式实现。

答案 1 :(得分:0)

您可以创建NSProxy的子类,根据您想要的每个条件,更改哪个对象将其方法转发给它。所以你的对象总是会指向NSProxy,但是你要成为AFOUsingString:将它转发的对象改为Foo。