2010-12-04 43 views
1

我來自Java背景的Objective-C。我無法理解爲什麼下面的代碼會生成異常。爲什麼目標C中的某些對象成員超出範圍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]; 

回答

5

在你的init

start = [NSDate date]; 

不使用起始屬性 - 它使用開始實例變量。這意味着保留從未被調用過。 [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

[NSDate date]給你一個自動釋放的情況下,當相關的自動釋放池被排幹,將被釋放。您必須保留它才能獲得所有權,請參閱Cocoa Memory Management上的文檔。