0

I understand that in Objective C 'instance variables are always initialized to 0 (or nil, NULL, or false, depending on the exact data type)'. stackoverflow question

In the unit test2 below, why is the instance variable _willBeRipeBy in the orange instance of Fruit not set to nil? It fails at STAssertNil([orange willBeRipeBy],nil).

test2 passes if I create an init method to explicitatly set _willBeRipeBy to nil or if I rename test1 to test3 to change the execution order.

Creating apple in test1 seems to be effecting the memory that orange uses but why is Fruits init not resetting the instance variable to nil.

I am new to objective C, Thanks.

(using Xcode 4.3, iOS5.0 with Automatic Reference Counting on)

@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
Community
  • 1
  • 1
ken
  • 3
  • 2
  • 1
    Don't prefix methods with `get`, btw. Just call it `willBeRipeBy` or `ripeDate` or `willBeRipeDate`. – bbum Mar 19 '12 at 16:24

2 Answers2

4

You have to declare the variable as an instance variable inside the header file or in {}-brackets after the @implementation directive.

Your implementation is a global variable

btw. you shouldn't name methods like "get..." - this is against cocoa naming conventions. You should only use "get.." when you want to set a non-object type with unknown size, e.g.: CGRect rect; [userInfoDictionary getValue:&rect forKey:@"bla"]
you can use properties (@property(strong) NSString *property and @synthesize property) to auto-implement instance variables along with getter and setter methods

Kristian Glass
  • 37,325
  • 7
  • 45
  • 73
Martin Ullrich
  • 94,744
  • 25
  • 252
  • 217
2

Because variables declared inside the implementation block are not instance variables, they are globals shared between class instances. And apparently globals are not guaranteed to be initialized to a sane value.

Your Fruit class should look like this:

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

@implementation Fruit
@synthesize willBeRipeBy;
@end
zoul
  • 102,279
  • 44
  • 260
  • 354