我是从Java背景来到Objective-C的。我无法理解为什么以下代码会生成异常。
@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
因此,当运行以下代码时,我发现stopwatch.start超出范围,但不是秒表?
Stopwatch *sw = [[Stopwatch alloc]init];
StopwatchControlelr *swc = [[StopwatchController alloc]init];
[swc useStopwatch:sw];
[swc updateStopwatch];
答案 0 :(得分:5)
在你的init
中start = [NSDate date];
不使用start属性 - 它使用start实例变量。这意味着从未调用过retain。 [NSDate date]返回一个将自动释放的对象。
我的建议是使用
self.start = [NSDate date];
这使用了该属性。在您的情况下,我还会声明此属性retain
,而不是assign
。如果保留assign
,则需要调用retain。所以使用assign
,也可以这样做
[self.start retain];
确保正确行事的一种方法是声明像这样的字段
NSDate * _start;
像这样的属性
@property (retain, nonatomic) NSDate * start;
然后像这样sythesize
@synthesize start = _start.
然后您知道何时使用实例变量(绕过任何设置调用,自动保留等)或属性。
如果你这样做,那就不会编译
start = [NSDate date];
您需要更改为此
self.start = [NSDate date]; // use property
或者
_start = [NSDate date]; // use instance variable
答案 1 :(得分:1)
[NSDate date]
为您提供一个自动释放的实例,当关联的自动释放池耗尽时,该实例将被释放。您必须保留它才能获得所有权,请参阅Cocoa Memory Management上的文档。