2016-09-19 77 views
0

代碼1使用 「_」 做任務:的iOS保留副本問題

@interface ViewController() 

@property (nonatomic,retain) NSMutableString *rrstr; 
@property (nonatomic,copy) NSMutableString *copystr; 

@end 

@implementation ViewController 

- (void)viewDidLoad { 
    [super viewDidLoad]; 

    NSMutableString *ssss = [[NSMutableString alloc]initWithString:@"ddddd"]; 
    _rrstr = ssss; 
    _copystr = ssss; 
    NSLog(@"%@===%@===%@",ssss,self.rrstr,self.copystr); 

    [ssss appendString:@"1231"]; 
    NSLog(@"%@===%@===%@",ssss,self.rrstr,self.copystr); 

    [ssss deleteCharactersInRange:NSMakeRange(1, 3)]; 
    NSLog(@"%@===%@===%@",ssss,self.rrstr,self.copystr); 
} 

代碼1輸出: 「」

2016-09-19 10:44:29.190 retin[1160:72426] ddddd===ddddd===ddddd 
2016-09-19 10:44:29.191 retin[1160:72426] ddddd1231===ddddd1231===ddddd1231 
2016-09-19 10:44:29.192 retin[1160:72426] dd1231===dd1231===dd1231 

碼2使用做任務:

@interface ViewController() 

@property (nonatomic,retain) NSMutableString *rrstr; 
@property (nonatomic,copy) NSMutableString *copystr; 

@end 

@implementation ViewController 

- (void)viewDidLoad { 
    [super viewDidLoad]; 

    NSMutableString *ssss = [[NSMutableString alloc]initWithString:@"ddddd"]; 
    self.rrstr = ssss; 
    self.copystr = ssss; 
    NSLog(@"%@===%@===%@",ssss,self.rrstr,self.copystr); 

    [ssss appendString:@"1231"]; 
    NSLog(@"%@===%@===%@",ssss,self.rrstr,self.copystr); 

    [ssss deleteCharactersInRange:NSMakeRange(1, 3)]; 
    NSLog(@"%@===%@===%@",ssss,self.rrstr,self.copystr); 


} 

碼2輸出:

2016-09-19 10:50:09.079 retin[1190:75922] ddddd===ddddd===ddddd 
2016-09-19 10:50:09.079 retin[1190:75922] ddddd1231===ddddd1231===ddddd 
2016-09-19 10:50:09.080 retin[1190:75922] dd1231===dd1231===ddddd 

我很困惑,爲什麼這兩個代碼具有不同的輸出?這些代碼不應該有相同的輸出嗎? 「_」和「。」之間的差異究竟是什麼?句法?

+0

更好地發佈代碼,而不是屏幕截圖 – Leo

回答

2

當您在Objective-C中聲明@property時,編譯器會爲您做一些事情。

  • 它創建一個支持實例變量來保存該屬性的值。默認情況下,這是_propertyName,但您可以用@synthesize指令
  • 覆蓋它。它會創建gettersetter函數。默認情況下,這些只需簡單地設置和獲取支持實例變量,但是您可以重寫這些函數並提供您自己的setter和getter實現。

很多人不正確地認爲_propertyName只是訪問該屬性的「捷徑」,但事實並非如此。它直接訪問後備變量,繞過setter和getter函數。

在許多情況下,它並不重要,但在某些情況下,它確實存在,其中之一就是您發現的情況,即copy屬性。

copy是財產,不是基本變量的屬性,所以當你宣佈

@property (nonatomic,copy) NSMutableString *copystr; 

的Objective-C創建一個看起來像下面的getter和setter函數:

-(NSMutableString *) copyStr { 
    return _copyStr; 
} 

-(void) setCopyStr: (NSMutableString *)value { 
    _copyStr = [value copy]; 
} 

所以,現在你可以看到之間的區別

_copyStr = ssss; // This is a straight pointer assignment 

self.copyStr = ssss; // This is actually a call to [self setCopyStr:ssss] 

在第一種情況下,setter不被調用,因此從不採取複製; _copyStr是對ssss字符串的引用,所以當您更改ssss時,由於它們引用的是同一個對象,因此該更改會反映在_copyStr中。

在第二種情況下,調用者被調用並且ssss被複制並且對新副本的引用被分配給_copyStr;現在,當更改ssss時,_copyStr所指的副本不受影響。

總之,你應該總是使用self.propertyName除非你有一個繞過setter/getter的特定原因。

+0

太棒了!謝謝! –