Как NSProxy «превращается в другой объект»? - PullRequest
11 голосов
/ 07 августа 2011

Ссылка класса NSProxy говорит это:

Как правило, сообщение прокси направляется реальному объекту или заставляет прокси загружать (или преобразовывать себя в) реальный объект.

Как именно «превратится в реальный объект»?

Чтобы сделать вещи немного более конкретными, предположим, что класс Foo имеет метод newFooWithString:, который принимает строку и возвращает новый экземпляр Foo. Возможно ли установить NSProxy, который сидит, и, если сообщение pleaseBecomeAFooUsingString: @"bar" получено, преобразуется в [Foo newFooWithString: @"bar"], занимая ту же самую память, не мешая другим ссылкам на себя, которые могут существовать?

Ответы [ 2 ]

6 голосов
/ 07 августа 2011

Если у вас есть указатель на один и тот же экземпляр 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 - это простой перенаправитель сообщений, никакой магии нет вообще, поэтому ваша цель не достижима так, как вы описали.

0 голосов
/ 08 августа 2011

Вы можете создать подкласс NSProxy, который изменяет, к какому объекту он направляет свои методы, в зависимости от того, какие критерии вы хотите.Таким образом, ваш объект всегда будет указывать на NSProxy, но вы, пожалуйста, BeaAAFooUsingString: измените объект, который он передает, как Foo.

...