为什么某些对象成员超出了Objective C的范围

Rob*_*hew 1 iphone memory-management objective-c

我是从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
Run Code Online (Sandbox Code Playgroud)

因此,当运行以下代码时,我看到stopwatch.start超出范围,但不是秒表?


Stopwatch *sw = [[Stopwatch alloc]init];
StopwatchControlelr *swc = [[StopwatchController alloc]init];
[swc useStopwatch:sw];
[swc updateStopwatch];
Run Code Online (Sandbox Code Playgroud)

Lou*_*nco 5

在你的初始化

start = [NSDate date];
Run Code Online (Sandbox Code Playgroud)

不使用start属性 - 它使用start实例变量.这意味着从未调用过retain.[NSDate date]返回一个将自动释放的对象.

我的建议是使用

self.start = [NSDate date];
Run Code Online (Sandbox Code Playgroud)

这使用了该属性.在你的情况下,我也会声明这个属性retain,而不是assign.如果你保留它assign,你需要调用retain.所以assign,也这样做

[self.start retain];
Run Code Online (Sandbox Code Playgroud)

确保正确执行的一种方法是声明这样的字段

NSDate * _start;
Run Code Online (Sandbox Code Playgroud)

像这样的属性

@property (retain, nonatomic) NSDate * start;
Run Code Online (Sandbox Code Playgroud)

然后像这样合成

@synthesize start = _start.
Run Code Online (Sandbox Code Playgroud)

然后,您知道何时使用实例变量(绕过任何设置调用,自动保留等)或属性.

如果你这样做,那么这将无法编译

   start = [NSDate date];
Run Code Online (Sandbox Code Playgroud)

你需要改变这个

   self.start = [NSDate date]; // use property
Run Code Online (Sandbox Code Playgroud)

或这个

   _start = [NSDate date]; // use instance variable
Run Code Online (Sandbox Code Playgroud)