Странная ошибка присваивания

Почему это работает:

- (void) setupInteraction:(IBITSInteraction*)interaction withInfo:(NSDictionary*)info
{    
    CGRect rect = ([info objectForKey:kInteractionFrameKey] ? CGRectFromString([info objectForKey:kInteractionFrameKey]) : CGRectZero);
    interaction.frame = rect;
    ...
}

а почему этого нет?

- (void) setupInteraction:(IBITSInteraction*)interaction withInfo:(NSDictionary*)info
{    
    interaction.frame = ([info objectForKey:kInteractionFrameKey] ? CGRectFromString([info objectForKey:kInteractionFrameKey]) : CGRectZero);
    ...
}

Я думаю, что точно так же...

  • Компилятор: LLVM GCC 4.2
  • Ошибка (второй случай): присвоение переменной только для чтения "prop.283"
  • Фрейм недвижимости: @property (nonatomic, assign) CGRect frame; с соответствующими @synthesize

Заранее спасибо.

2 ответа

Решение

Это ошибка в интерфейсе GCC 4.2, также воспроизводимая в LLVM-GCC 4.2. Поздравляем! Эти компиляторы сталкиваются с проблемами при назначении свойств с использованием точечного синтаксиса, когда присваиваемое значение является выражением, полученным в результате условного оператора.

Следующий код воспроизводит проблему и показывает два решения исходного кода: один, как вы заметили, использует временную переменную. Другое решение заключается в использовании традиционного синтаксиса отправки сообщений Objective-C вместо точечного синтаксиса:

#import <Foundation/Foundation.h>

CGRect CGRectFromString(NSString *string);

@interface SomeClass : NSObject
@property (nonatomic, assign) CGRect frame;
@end

@implementation SomeClass
@synthesize frame;
@end

int main(void) {
    NSDictionary *info;
    SomeClass *interaction;
    NSString *kInteractionFrameKey;

    CGRect rect;
    rect = [info objectForKey:kInteractionFrameKey] ? CGRectFromString([info objectForKey:kInteractionFrameKey]) : CGRectZero;
    interaction.frame = rect;

    [interaction setFrame:([info objectForKey:kInteractionFrameKey] ? CGRectFromString([info objectForKey:kInteractionFrameKey]) : CGRectZero)];

    interaction.frame = ([info objectForKey:kInteractionFrameKey] ? CGRectFromString([info objectForKey:kInteractionFrameKey]) : CGRectZero);
    interaction.frame = ([info objectForKey:kInteractionFrameKey] ? CGRectZero : CGRectFromString([info objectForKey:kInteractionFrameKey]));
    interaction.frame = ([info objectForKey:kInteractionFrameKey] ? CGRectZero : CGRectZero);

    return 0;
}

Тестирование с разными компиляторами дает следующее:

$ llvm-gcc -c test.m
test.m: In function ‘main’:
test.m:24: error: assignment of read-only variable ‘prop.76’
test.m:25: error: assignment of read-only variable ‘prop.77’
test.m:26: error: assignment of read-only variable ‘prop.78’

$ clang -c test.m
$

Вы можете использовать LLVM или избежать точечного синтаксиса в этом конкретном случае. Возможно, вы захотите сообщить об ошибке, но я бы не стал задерживать дыхание, поскольку Apple вряд ли обновит GCC.

Я пробовал этот код в общем методе уведомлений в GCC 4.2, LLVM GCC 4.2 и Apple LLVM 2.1. Никто из них не дал мне ошибок. Итак, что-то происходит с вашей установкой Xcode и / или установкой компилятора.

Другие вопросы по тегам