2016-09-19 183 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

太棒了!谢谢! –