开发者

Why are some object members out of scope in Objective C

I'm coming to Objective-C from a Java background. I'm having trouble understanding why the following code generates an exception.

    
@interface Stopwatch : NSObject {
    NSDate *start;
    int    mode;
}
@property(nonatomic,assign) NSDate *start;
@property(nonatomic,assign) int mode;
@end

@implementation Stopwatch
@synthesize start, mode;
-(id) init{
    self = [super init];
    if(self){
        start = [NSDate date];
        mode = -1;
    }
    return self;
}
@end


@interface StopwatchController : NSObject {
    Stopwatch *stopwatch;
}
@property (nonatomic,assign) Stopwatch *stopwatch;

- (void) useStopwatch:(Stopwatch*)aStopwatch;
- (void) updateStopwatch;
@end

@implementation StopwatchController
@synthesize stopwatch;

- (void) useStopwatch:(Stopwatch*)aStopwatch{
    stopwatch = aStopwatch;
}

- (void) updateStopwatch{
    NSDateFormatter *dateFormat = [[NSDateFormatter alloc]init];
    [dateFormat setTimeStyle:NSDateFormatterMediumStyle];
    [dateFormat setDateStyle:NSDateFormatterMediumStyle];
    NSString *string = [dateFormat stringFromDate:stopwatch.start];
    NSLog(@"%@",string);
}
@end

So when the following code is run I see tha开发者_开发知识库t the stopwatch.start is out of scope, but not the stopwatch?


Stopwatch *sw = [[Stopwatch alloc]init];
StopwatchControlelr *swc = [[StopwatchController alloc]init];
[swc useStopwatch:sw];
[swc updateStopwatch];


In your init

start = [NSDate date];

Does not use the start property -- it uses the start instance variable. This means that a retain was never called. [NSDate date] returns an object that will autorelease.

My advice is to use

self.start = [NSDate date];

This uses the property. In your case, I would also declare this property retain, not assign. If you keep it assign, you need to call retain. So with assign, also do this

[self.start retain];

One way to make sure you do it right is to declare fields like this

NSDate * _start;

Properties like this

@property (retain, nonatomic) NSDate * start;

and then sythesize like this

@synthesize start = _start.

Then you know when you are using the instance variable (which bypasses any set calls, automatic retains, etc) or the property.

If you did that, then this would not compile

   start = [NSDate date];

You'd either need to change to this

   self.start = [NSDate date]; // use property

or this

   _start = [NSDate date]; // use instance variable


[NSDate date] gives you an autoreleased instance which will be deallocated when the associated autorelease pool is drained. You have to retain it to take ownership, see the documentation on Cocoa Memory Management.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜