Почему переменная экземпляра (очевидно) не установлена ​​​​в ноль при инициализации?

Я понимаю, что в Objective C «переменные экземпляра всегда инициализируются 0 (или nil, NULL или false, в зависимости от точного типа данных)». вопрос о переполнении стека

Почему в модульном тесте2 ниже переменная экземпляра _willBeRipeBy в оранжевом экземпляре Fruit не установлена ​​на nil? Он терпит неудачу в STAssertNil([orange willBeRipeBy],nil).

test2 проходит, если я создаю метод init, чтобы явно установить _willBeRipeBy в nil, или если я переименую test1 в test3, чтобы изменить порядок выполнения.

Создание apple в test1, по-видимому, влияет на память, которую использует orange, но почему Fruits init не сбрасывает переменную экземпляра в ноль.

Я новичок в задаче C, спасибо.

(с использованием Xcode 4.3, iOS5.0 с включенным автоматическим подсчетом ссылок)

@interface Fruit : NSObject
- (NSDate *)getWillBeRipeBy;
- (void)setWillBeRipeBy:(NSDate *)ripeBy;
@end

@implementation Fruit

NSDate *_willBeRipeBy;

- (NSDate *)getWillBeRipeBy{
    return _willBeRipeBy;
}
- (void)setWillBeRipeBy:(NSDate *)ripeBy{
    _willBeRipeBy = ripeBy;
}
@end

@implementation TestIvarInitialisationTests

- (void)test1
{
    Fruit *apple = [[Fruit alloc] init];
    STAssertNil([apple getWillBeRipeBy],nil);
    NSDate * now = [NSDate date];
    [apple setWillBeRipeBy:now];
    STAssertEqualObjects([apple getWillBeRipeBy], now,nil);
}

- (void)test2
{
    Fruit *orange = [[Fruit alloc] init];
    STAssertNil([orange getWillBeRipeBy],nil);
}
@end

person ken    schedule 19.03.2012    source источник
comment
Кстати, не добавляйте к методам префикс get. Просто назовите его willBeRipeBy или ripeDate или willBeRipeDate.   -  person bbum    schedule 19.03.2012


Ответы (2)


Вы должны объявить переменную как переменную экземпляра внутри файла заголовка или в квадратных скобках {} после директивы @implementation.

Ваша реализация является глобальной переменной

кстати. вы не должны называть такие методы, как "get..." - это противоречит соглашениям об именах какао. Вы должны использовать «get..» только тогда, когда вы хотите установить необъектный тип с неизвестным размером, например: CGRect rect; [userInfoDictionary getValue:&rect forKey:@"bla"]
вы можете использовать свойства (@property(strong) NSString *property и @synthesize property) для автоматической реализации переменных экземпляра вместе с геттером и сеттером методы

person Martin Ullrich    schedule 19.03.2012

Поскольку переменные, объявленные внутри блока реализации, не являются переменными экземпляра, они являются глобальными переменными, общими для экземпляров класса. И, по-видимому, глобальные переменные не гарантированно будут инициализированы до разумного значения.

Ваш класс Fruit должен выглядеть так:

@interface Fruit : NSObject
@property(strong) NSDate *willBeRipeBy;
@end

@implementation Fruit
@synthesize willBeRipeBy;
@end
person zoul    schedule 19.03.2012