copy or strong

MRC下重写setter和getter方法

代码如下:

#import <Foundation/Foundation.h>

@interface Person : NSObject

@property (nonatomic, copy) NSString *name;

@end

#import "Person.h"

@implementation Person

@synthesize name = _name;

- (void)setName:(NSString *)name{
    if (_name != name) {
        [_name release];
        _name = [name copy];
    }
}

- (NSString *)name{
    return _name;
}
@end

copy和setter的选择

总结:

  • 对于不可变对象(NSString、NSArray、NSDictionary等),使用copy修饰。
  • 对于可变对象(NSMutableString、NSMutableArray、NSMutableDictionary等),使用strong修饰。
crash问题

把NSMutableArray用copy修饰有时就会crash,因为对这个数组进行了增删改操作,而copy后的数组变成了不可变数组NSArray,没有响应的增删改方法,所以对其进行增删改操作就会报错。

测试过程
以数组为例总结:

#import "ViewController.h"

@interface ViewController ()

@property (nonatomic, strong) NSMutableArray *arr_strong;
@property (nonatomic, copy) NSMutableArray *arr_copy;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    NSMutableArray *tempArr = [NSMutableArray arrayWithCapacity:0];
    self.arr_strong = tempArr;
    self.arr_copy = tempArr;
    NSLog(@"arr_strong = %@\n arr_copy = %@",[self.arr_strong class],[self.arr_copy class]);
}

@end

输出结果

arr_strong = __NSArrayM(可变数组)
arr_copy = __NSArray0(不可变数组)

所以此时如果对arr_copy进行增删改操作,会造成程序上的崩溃。

数据变化问题

条件:
针对数据变化的问题,会在将可变对象赋值给用strong修饰的不可变对象时产生。

测试代码

#import "ViewController.h"

@interface ViewController ()

@property (nonatomic, strong) NSArray *arr_strong;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    NSMutableArray *tempArr = [NSMutableArray arrayWithCapacity:0];
    [tempArr addObject:@"A"];
    self.arr_strong = tempArr;
    NSLog(@"arr_strong = %@",self.arr_strong);
    [tempArr addObject:@"B"];
     NSLog(@"arr_strong = %@",self.arr_strong);
}

@end

输出结果

 arr_strong = (
    A
)
arr_strong = (
    A,
    B
)

如果把arr_strong属性修饰改成copy
输出结果

 arr_strong = (
    A
)
 arr_strong = (
    A
)
copy collections

深拷贝和浅拷贝的区别
如下图所示:


浅拷贝就是指针拷贝;深拷贝就是内容拷贝。

copy和mutableCopy
1.不可变对象使用copy,是一个浅拷贝。
2.不可变对象使用mutableCopy,深拷贝。
3.可变对象copy和mutableCopy,都是深拷贝。
但是对于集合类对象来说:上面的深拷贝都是单层深拷贝,并非完全深拷贝。

集合类对象实现单层深拷贝
initWithArray:copyItems: 将第二个参数设置为YES即可深复制。

NSArray *deepCopyArray=[[NSArray alloc] initWithArray: array copyItems: YES];

deepCopyArray内部存储元素,对于不可变元素是指针拷贝,对于可变元素是内容拷贝。类似于内部每个元素调用了copy方法。

集合类对象实现完全深拷贝
将集合进行归档(archive),然后解档(unarchive)。

NSArray *trueDeepCopyArray = [NSKeyedUnarchiver unarchiveObjectWithData:[NSKeyedArchiver archivedDataWithRootObject:oldArray]];

参考资料:

Copying Collections
iPhone Dev:iOS开发之深拷贝与浅拷贝(mutableCopy与Copy)详解
Blog:copy 与 mutableCopy

推荐阅读更多精彩内容

  • 本文为转载: 作者:zyydeveloper 链接:http://www.jianshu.com/p/5f776a...
    iOS_404阅读 228评论 0 2
  • 转别人的,之前看过两遍总是忘记,索性自己保存一份 我们在声明一个NSString属性时,对于其内存相关特性,通常有...
    酥比特阅读 538评论 0 3
  • 上次面试中,面试官问的问题,我总是习惯于使用Copy,但是里面究竟有什么区别,我没有很好的表达出来,这次通过几个简...
    忆昔溪阅读 24评论 0 0
  • 结论 对于copy修饰的属性来说,若赋值源是NSString、NSArray、NSURLRequest三者其中之一...
    JiandanDream阅读 618评论 7 4
  • 前言 不敢说覆盖OC中所有copy的知识点,但最起码是目前最全的最新的一篇关于 copy的技术文档了。后续发现有新...
    zyydeveloper阅读 947评论 4 22