iOS保留副本问题

时间:2016-09-19 02:46:45

标签: ios

code1使用“_”进行分配:

 $user=User::where(['id'=>Auth::user()->id])->with('questions','answers','comments','comments.votes','votes')
    ->first(); 

code1输出:

@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);
}

code2使用“。”做任务:

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

code2输出:

@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);


}

我很困惑为什么这两个代码有不同的输出?这些代码不应该具有相同的输出吗? “_”和“。”之间的区别究竟是什么。语法?

1 个答案:

答案 0 :(得分: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中,因为它们引用了同一个对象。

在第二种情况下,调用setter并复制ssss,并将对新副本的引用分配给_copyStr;现在,当ssss更改时,_copyStr引用的副本不受影响。

简而言之,除非您有特定理由绕过setter / getter,否则总是使用self.propertyName