iOS 保留复制问题

标签 ios

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

code1 输出:

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


}

code2输出:

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

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

最佳答案

当您在 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 时,该更改会反射(reflect)在 _copyStr 中,因为它们引用同一个对象。

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

简而言之,您应该始终使用self.propertyName,除非您有特定原因绕过 setter/getter。

关于iOS 保留复制问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39564671/

相关文章:

objective-c - iOS4上的iOS5类

ios - 在 64 位处理器上运行时出现 Core Audio 错误

ios - 尝试将 UIGraphicsImageRenderer 与 SCNView 一起使用会产生空结果

ios - UISplitViewController 不会在横向模式下隐藏 masterViewController

ios - UITableView 没有显示它应该显示的 Realm 对象

ios - PHPhotoLibrary 错误 : content editing in performChanges results in error "The operation couldn’ t be completed.(Cocoa 错误 -1。)”

ios - 应用反馈表

ios - Swift 中 UIKit 协议(protocol)的扩展

iphone - 错误 : "No devices registered in member center" - Invalid UDID?

ios - 避免/禁用 iOS 中的状态保存