Получение класса возвращаемого объекта в Objective-C - PullRequest
3 голосов
/ 10 февраля 2012

Я пытаюсь реализовать в Objective-C прокси для объекта следующим образом:

- (NSMethodSignature*) methodSignatureForSelector:(SEL)sel
{
    return [_proxifiedObject methodSignatureForSelector:sel];
}

- (void) forwardInvocation:(NSInvocation *)invocation
{
    char returnType = invocation.methodSignature.methodReturnType[0];
    if(returnType == '@')
    {
        id anotherProxy = [[[MyProxy alloc] initWithInvocation:invocation] autorelease];
        [invocation setReturnValue:&anotherProxy];
    } else {
        invocation.target = _proxifiedObject;
        [invocation invoke];
    }
}

Другой прокси должен создать объект из этого вызова.Но пока объект находится в стадии разработки, мы должны иметь возможность собирать и хранить вызовы к нему, чтобы иметь возможность обработать их после того, как объект будет построен.Для достижения этого я должен реализовать 2 метода: methodSignatureForSelector: и forwardInvocation :.Второе довольно просто, но первое, о чем весь вопрос.

Мы должны знать класс проксифицированного объекта, чтобы иметь возможность предоставить подпись, но вызов, с которым инициализируется другойProxy, не предоставляет информацию о классе возвращаемого объекта.Есть ли способ получить класс объекта, который будет возвращен методом с использованием среды выполнения Apple Objective-C?

ОБНОВЛЕНИЕ :

Я понимаю, что фактическоекласс возвращаемого объекта может отличаться, но может быть единственный класс, с которым объявлен метод.Если метод объявлен как

 - (SomeClass*) someMethod;

в интерфейсе, я ожидаю получить SomeClass.

ОБНОВЛЕНИЕ :

Наконец я решил своюпроблема.Решение не элегантное, но оно «просто работает».Я написал этот метод:

static NSMutableDictionary* dictionarySelectorsToSignatures;

+ (NSMethodSignature*) methodSignatureForUnknownClassForSelector: (SEL) sel
{
    NSMethodSignature* candidate = [dictionarySelectorsToSignatures objectForKey:[NSNumber numberWithLongLong:(long long) sel]];
    if(candidate == nil)
    {
        int classesCount = objc_getClassList(NULL, 0);
        Class* classes = malloc(sizeof(Class) * classesCount);
        objc_getClassList(classes, classesCount);
        for(int i = 0; i < classesCount; i++)
        {
            if(class_getClassMethod(classes[i], @selector(instanceMethodSignatureForSelector:)) != NULL)
            {
                NSMethodSignature* signature = [classes[i] instanceMethodSignatureForSelector:sel];
                if(signature != nil)
                {
                    if(candidate != nil)
                    {
                        if(![candidate isEqual:signature])
                        {
                            return nil;
                        }
                    } else {
                        candidate = signature;
                    }
                }
            }
        }
        if(candidate != nil)
        {
            [dictionarySelectorsToSignatures setObject:candidate 
                                                forKey:[NSNumber numberWithLongLong:(long long)  sel]];
        }
    }
    return candidate;
}

Этот метод возвращает подпись для селектора, если он не является неоднозначным и ноль в другом случае.Его основным недостатком является тот факт, что он не поддерживает модификацию классов / списков классов во время выполнения, поэтому его можно использовать только в том случае, если все классы зарегистрированы и код не изменяет классы (потенциально рискованно использовать его с KVO!).

Ответы [ 3 ]

2 голосов
/ 11 февраля 2012

Есть ли способ получить класс объекта, который будет возвращен методом, используя среду выполнения Apple Objective-C?

Нет - если метод возвращает тип класса, вы не можете знать фактический - конкретный - тип, прежде чем он вернется. Поскольку конкретный тип класса неизвестен, вы не можете узнать, какой тип возврата может иметь любой из его методов.

0 голосов
/ 10 февраля 2012

Вы можете получить фактическое имя класса объекта:

например, для объекта foo

NSLog(@"foo is an object of class %@", NSStringFromClass([foo class]));
0 голосов
/ 10 февраля 2012

Вот как проверить, является ли "instance" NSString

if ([instance isKindOfClass:[NSString class]]( {
  //do something
}

Это хорошо?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...