iOS之strong和copy

深拷贝和浅拷贝

深拷贝和浅拷贝主要是对类类型而言的,浅拷贝就是指针拷贝,深拷贝是对象拷贝。

property的strong和copy

在接触iOS程序时经常会看到程序某些类类型属性被strong修饰,某些被copy修饰,刚开始接触时有些疑惑,后来不知咋地形成了这样的观念,对于mutable类型,用copy修饰,对于immutable类型,用strong修饰,现在看来这个大大地错了。

创建属性是一件机械化的工作:对于一般的属性,你会将它们声明为 nonatomic。默认情况下,对象属性是strong的,标量属性是assign的。但是有一个例外,就是对于具有可变副本的属性,我们倾向于将其声明为 copy。比如说,name属性的类型是NSString,有可能有人创建了一个Person对象,并且给这个属性赋了一个NSMutableString的名字值。然后过了一会儿,这个可变字符串被变更了。如果我们的属性不是copy而是strong的话,随着可变字符串的改变,我们的Person对象也将发生改变,这不是我们希望发生的。对于类似数组或者字典这样的容器类来说,也是这样的情况。

简单来说,对于被strong修饰property,在对其赋值时,并不是真正拷贝,而只是将右值的retain count加1,将左值的指针改为右值(也是一个指针)所指向的地址,直观来看,即赋值后左值和右值的地址值是一样一样的,即浅拷贝;
但对于被copy所修饰的property且它遵循NSCopying协议,在为property赋值时,赋值语句不会保留新值(变量不会随可变字符串的改变而改变),直观来看,赋值后左值和右值的地址值可能不同,也即“赋值语句可能是深拷贝,也可能是浅拷贝”;
P.S:这里为什么说“可能”呢?下文会对这个问题进行阐述。
P.S:对于属性的赋值,单纯理解为浅拷贝或深拷贝操作是不对的,因为还会改变retain count的值(对于浅拷贝而言)。

举个栗子:

// 两个属性,前者用copy修饰,后者用strong修饰
@property (nonatomic, copy) NSString *firstName;
@property (nonatomic, strong) NSString *lastName;

NSMutableString *str1 = [NSMutableString stringWithString:@"不坏"];
self.firstName = str1;		// 赋值
// 打印左值和右值的地址值
NSLog(@"str1 addr: 0x%lx", str1);
NSLog(@"self.first addr: 0x%lx", self.firstName);

NSLog(@"");

NSMutableString *str2 = [NSMutableString stringWithString:@"张"];
self.lastName = str2;		// 赋值
// 打印左值和右值的地址值
NSLog(@"str2 addr: 0x%lx", str2);
NSLog(@"lastName addr: 0x%lx", self.lastName);

打印结果是:

str1 addr: 0x7967f580
self.first addr: 0x7967f1d0

str2 addr: 0x7967f460
lastName addr: 0x7967f460

显然,对于用copy修饰的firstName,其赋值所采用的方式是深拷贝;对于用strong修饰的lastName,赋值方式是浅拷贝。

回过头来解释上述的“可能”。

其实很简单,对于赋值语句self.firstName = str1;(firstName被copy修饰),如果右值str1是mutable,则这条语句处理的方式是深拷贝。因为如果str1是mutable,并且执行浅拷贝的话,这就意味着如果str1改变了,则self.firstName也会跟着改变,这是我们不希望的,所以执行深拷贝时合理的;如果右值str1是immutable,则赋值语句所处理的方式依然是浅拷贝,因为反正str1不会再发生改变了,对self.firstName值不会有意想不到的影响,此时进行深拷贝有些浪费。

P.S:Objective-C的这种设计理念略显啰嗦,比较智能的处理方法是当str1改变时,彼时再进行深拷贝处理,很多现代语言都是这么弄的,譬如Python。

总结:property的关键字copy的本意是为了保护“immutable属性在被mutable右值对象赋值后不被右值之后可能发生的改变所影响”,而对mutable属性,则不存在这样的问题。

时间: 2024-11-06 03:44:08

iOS之strong和copy的相关文章

IOS开发 strong,weak,retain,assign,copy nomatic 等的区别与作用

strong,weak,retain,assign,copy nomatic 等的区别 copy与retain:1.copy其实是建立了一个相同的对象,而retain不是:2.copy是内容拷贝,retain是指针拷贝:  3.copy是内容的拷贝 ,对于像NSString,的确是这样,但是如果copy的是一个NSArray呢?这时只是copy了指向array中相对应元素的指针.这便是所谓的"浅复制".4.copy的情况:NSString *newPt = [pt copy];此时会在

iOS 关键词assign、strong、copy、weak、unsafe_unretained

关键词assign.strong.copy.weak.unsafe_unretained 影响: 是否开辟新的内存 是否有引用计数增加 strong 指向并拥有该对象.其修饰的对象引用计数会 +1,该对象只要引用计数不为 0 就不会销毁,置为 nil 可以销毁它.一般用于修饰对象类型.字符串.集合类的可变版本NSMutable. // .h 文件 @property (nonatomic, strong) NSMutableArray * nArr; // .m 文件 { NSMutableAr

18-NSString之Strong和copy

NSString属性什么时候用copy,什么时候用strong? 2015-05-12  iOS开发 我们在声明一个NSString属性时,对于其内存相关特性,通常有两种选择(基于ARC环境):strong与copy.那这两者有什么区别呢?什么时候该用strong,什么时候该用copy呢?让我们先来看个例子. 示例   我们定义一个类,并为其声明两个字符串属性,如下所示: @interface TestStringClass () @property (nonatomic, strong) NS

关于@property()的那些属性及ARC简介【nonatomic,atomic,assign,retain,strong,weak,copy。】

@property()常用的属性有:nonatomic,atomic,assign,retain,strong,weak,copy. 其中atomic和nonatomic用来决定编译器生成的getter和setter是否为原子操作. NSObject对象的@property属性时,默认为atomic,提供多线程安全. 在多线程环境下,原子操作是必要的,否则有可能引起错误的结果.加了atomic,setter函数会变成下面这样: NSLock *_lock = [[NSLock alloc]ini

IOS中Retain和Copy的区别

IOS中Retain和Copy的区别 1 ,可读性: readonly  . readwrite@property(readwrite,....) valueType value;这个属性是变量的默认属性,就是如果你 (readwrite and readonly 都没有使用,那么你的变量就是 readwrite 属性 ) ,通过加入 readwrite 属性你的变量就会有 get 方法,和 set 方法.property(readonly,...) valueType value;这个属性变量

retain strong 和 copy 讨论,有建议的的童鞋请留言

总结下我的理解: strong weak是ARC引入的,strong相当于retain,但是对于有的类型,例如NSString,则使用strong相当于使用copy 这样直接用strong就可以直接处理retain和strong的情况了. weak相当于assign,但是比后者多一点:对象被干掉时会将weak引用设为nil,而对nil发送消息都不会导致崩溃 否则weak引用为野指针,会出现问题 这里说strong 有copy的功能是错误的哦.实验例子 @interface AppDelegate

strong和copy的区别

strong和copy的区别 问题描述 在定义一个类的property时候,为property选择strong还是copy特别注意和研究明白的,如果property是NSString或者NSArray及其子类的时候,最好选择使用copy属性修饰.为什么呢?这是为了防止赋值给它的是可变的数据,如果可变的数据发生了变化,那么该property也会发生变化. 代码示例 还是结合代码来说明这个情况 @interface Person : NSObject @property (strong, nonat

iOS中assign、copy 、retain等关键字的含义

assign: 简单赋值,不更改索引计数copy: 建立一个索引计数为1的对象,然后释放旧对象 retain:释放旧的对象,将旧对象的值赋予输入对象,再提高输入对象的索引计数为1 Copy其实是建立了一个相同的对象,而retain不是:比如一个NSString对象,地址为0×1111,内容为@"STR" Copy到另外一个NSString之 后,地址为0×2222,内容相同,新的对象retain为1, 旧有对象没有变化 retain到另外一个NSString之 后,地址相同(建立一个指

retain、strong和copy测试

时不时会有点迷惑retain.strong.copy三者之间的区别,还是记录下来好一点,先看代码: 创建一个类,定义属性 #import <Foundation/Foundation.h> @interface Person : NSObject @property (nonatomic, retain) NSString *strRetain; @property (nonatomic, strong) NSString *strStrong; @property (nonatomic, c