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.
精彩评论