美文网首页
Objective-C中的copy

Objective-C中的copy

作者: sunshinfight | 来源:发表于2019-02-27 21:08 被阅读0次

copy 关键字的作用

从一个例子说起:

@interface Person : NSObject
@property (nonatomic, copy) NSString *name;
@end
Person *xiaohong = [[Person alloc] init];

这段代码中NSString为什么要加上copy关键字呢?

copy关键字的作用是,调用obj(已经遵从NSCoding)的copyWithZone:,并将返回值赋值给实例变量

copy关键字的作用 深浅拷贝
上图说明了深浅拷贝的内存分配情况,不分配内存的情况下,将增加引用计数(ARC)。

容易疑惑的地方:

  1. B2 为什么是浅拷贝
  2. C3 为什么不安全
  3. E2 为什么不安全
  4. D3 为什么不安全

不可变类型(以NSString为例)

NSString类比C++代码如下(未区分堆栈):

NSString *strOC = @"hello oc";     // 指针是可变的,但是所指的内存区域是不可变的
const char strC[] = "hello cpp";   // c++下类似的情况
strOC = @"new"; // strOC指向的区域发生变化
内存2

疑惑点1

形如

@property (copy) NSString *name; // Person中定义

xiaohong.name = [NSString stringWithFormat:@"xiaohong"];

在不可变类型的属性指定了copy关键字后,并没有分配新的内存,这是因为已经指定属性为不可变的类型,所以此块内存区域的值是不会发生变化,这是为了为节约内存和提高效率(分配回收内存需要时间)。

疑惑点2

考虑如下代码

@property (copy) NSString *name; // Person中定义

NSMutableString *name = [NSMutableString stringWithFormat:@"xiaohong"];
xiaohong.name = name;
[name appendString:@" Zhang"];
NSLog(@"%@", xiaohone.name); // "xiaohong zhang"

这里说的不安全是因为在类中已经将name定义为NSString类型,所以说希望该内存是不可变的,但是又在外部修改了它的值,与期望相悖,而且用NSString的指向一个NSMutableNSString这也是不安全的。

疑惑点3

考虑如下代码

@property NSMutableString *name; // Person中定义

xiaohong.name = [NSString stringWithFormat:@"xiaohong"];
[xiaohone.name appendString:@" zhang"]; // crash

造成crash的原因为向NSString发送了appendString:的消息,但是NSString不能处理此消息。因为copy关键字调用copyWithZone:,生成的是不可变类型(即NSString),即使指针被转换为了NSMutableString类型,但是runtime会根据class中的信息发送消息。

copy 的作用如下

@property NSMutableString *name; // Person中定义

// setter中:self.name = [[NSString stringWithFormat:@"xiaohong"] copy];  
// self.name实际是NSString类型
xiaohong.name = [NSString stringWithFormat:@"xiaohong"];
[xiaohone.name appendString:@" zhang"]; // crash

疑惑点4

@property (copy) NSMutableString *name; // Person中定义

// setter中:self.name = [[NSMutableString stringWithFormat:@"xiaohong"] copy];  // copy 产生的不可变对象NSString
// self.name实际是NSString类型
xiaohong.name = [NSMutableString stringWithFormat:@"xiaohong"];
[xiaohone.name appendString:@" zhang"]; // crash, 因为name的类型是NSString

对于OC中容器类型的拷贝

容器类型的行为与OC中其他引用类型的行为是一致的。所以说如果容器中存放的是引用类型,则即使发生深拷贝,也只是拷贝了容器中的引用。所以说容器的深拷贝只是对容器来说的。

例如

NSMutableString *mStr = [NSMutableString stringWithFormat:@"xiaohong"];
NSMutableArray *mAry = [NSMutableArray arrayWithObject:mStr];
NSMutableArray *mCAry = mAry.mutableCopy;
[mstr appendString: @" zhang"];
// mAry[0]与mCAry[0]指向相同内存
NSLog(mAry[0]);    // "xiaohong zhang"
NSLog(mCAry[0]);   // "xiaohong zhang"

copymutableCopy属性将分别调用copyWithZone:mutableCopyWithZone:

把自定义的类作为有copy关键字的属性

需要实现copyWithZone:,如果自定义的类包含可变和不可变两种类型,则需要分别实现copyWithZone:mutableCopyWithZone:copy的行为是自己定义的,当然正常情况下应该是定义为深拷贝。

相关文章

  • 浅拷贝&深拷贝|| MutableCopy& C

    浅拷贝(Shallow Copy)与深拷贝(Deep Copy) 在Objective-C中并不是所有的对象都支持...

  • Objective-C中的copy

    copy 关键字的作用 从一个例子说起:@interface Person : NSObject@property...

  • objc NSString copy

    关于 Objective-C 中 NSString 在什么时候用 copy 的 特性 @property (non...

  • Copy和MutableCopy

    一、从面向对象到Objective-C概览copy 面向对象: 在面向对象的程序设计中,对象的copy就是创建一个...

  • 浅拷贝(Shallow Copy)与深拷贝(Deep Copy)

    概念 在Objective-C中并不是所有的对象都支持Copy,MutableCopy,遵守NSCopying协议...

  • (iOS) Swift

    Swift 与 Objective-C 比较 String & NSString Copy On Write

  • iOS - copy/strong

    copy/Strong的区别 修饰属性时的区别 NSString在Objective-C中中是一种非常特殊的对象,...

  • 关于 Objective-C 中的 copy

    通常, 我们在定义 不可变字符串和不可变集合 的时候, 会用到 copy 这个存储属性, 那我们为何要用 copy...

  • Objective-C中的copy方法

    对象的复制就是复制一个对象作为副本,他会开辟一块新的内存(堆内存)来存储副本对象,就像复制文件一样,计源对象和副本...

  • Objective-C copy那些事儿

    写在前面 Objective-C中的copy相关内容比我想象中要丰富多了。 NSCopying和NSMutable...

网友评论

      本文标题:Objective-C中的copy

      本文链接:https://www.haomeiwen.com/subject/vasquqtx.html