Вопрос

Следующий код реализует подкласс NSProxy, который пересылает методы экземпляру NSNumber.

Однако при вызове [nsproxy floatValue] я получаю 0,0 в GCC 4.2.

Под LLVM-Clang я получаю правильный ответ 42.0.

Есть идеи, что происходит?

(кстати, это работает в разделе «Сборка мусора»)

-(id) init;
{
    _result = [NSNumber numberWithFloat:42.0];
    return self;
}

- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
{
    return [[_result class] instanceMethodSignatureForSelector:aSelector];
}

- (void)forwardInvocation:(NSInvocation *)anInvocation
{
    [anInvocation setTarget:_result];
    [anInvocation invoke];
    return;
} 
Это было полезно?

Решение

Ваш прокси-класс не объявляет подпись сообщения для -floatValue.Поскольку он возвращает число с плавающей запятой, это может быть проблемой.Поскольку вы нигде его не объявили и, по-видимому, не приводите свой прокси-объект к представленному ему классу, компилятору приходится угадывать сигнатуру метода.В этом случае компилятор GCC предполагает, что сообщение вернет id указатель.

В Objective-C, в зависимости от подписи сообщения и архитектуры машины, для обработки сообщения и его возвращаемых значений используются разные функции.На машинах x86 сообщения, возвращающие значение с плавающей запятой, вызываются через objc_msgSend_fpret в то время как функции, которые возвращают void и id использовать objc_msgSend.

Поскольку компилятор GCC предполагает, что возвращаемое значение является id он использует последнюю функцию и неправильно обрабатывает результат.То, что Clang способен правильно с этим справиться, интересно, но я бы не стал полагаться на такое поведение.Было бы лучше объявить категорию на вашем прокси для всех методов, которые вы будете пересылать.Это также дает преимущество в удалении предупреждения, которое создавалось для строки кода, вызывающей floatValue метод.

@interface Foo (ProxyMethods)
- (float)floatValue;
@end

Другие советы

Любой init метод должен вызывать [super init]; для предотвращения неожиданного поведения.Итак:

- (id)init {
    self = [super init];
    if (self) {
        // Your init code
    }
    return self;
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top