深.浅拷贝
- copy/mutableCopy NSString
NSString *string = @"汉斯哈哈哈";
// 没有产生新对象
NSString *copyString = [string copy];
// 产生新对象
NSMutableString *mutableCopyString = [string mutableCopy];
NSLog(@"string = %p copyString = %p mutableCopyString = %p", string, copyString, mutableCopyString);
- copy/mutableCopy NSMutableString
NSMutableString *string = [NSMutableString stringWithString:@"汉斯哈哈哈"];
// 产生新对象
NSString *copyString = [string copy];
// 产生新对象
NSMutableString *mutableCopyString = [string mutableCopy];
NSLog(@"string = %p copyString = %p mutableCopyString = %p", string, copyString, mutableCopyString);
结论:
注意:其他对象NSArray、NSMutableArray 、NSDictionary、NSMutableDictionary一样适用
- copy NSObject
HSPerson *p = [[HSPerson alloc] init];
p.age = 20;
p.height = 170.0;
HSPerson *copyP = [p copy]; // 这里崩溃
崩溃:
看崩溃信息HSPerson应该先实现:
- (id)copyWithZone:(NSZone *)zone;
测试:
#import "HSPerson.h"
@interface HSPerson()<NSCopying>
@end
@implementation HSPerson
- (id)copyWithZone:(NSZone *)zone
{
return @"汉斯哈哈哈";
}
@end
HSPerson *p = [[HSPerson alloc] init];
p.age = 20;
p.height = 170.0;
HSPerson *copyP = [p copy];
NSLog(@"copyP: %@", copyP);
可以看出copyWithZone重新分配新的内存空间,则:
- (id)copyWithZone:(NSZone *)zone
{
HSPerson *person = [[HSPerson allocWithZone:zone] init];
return person;
// 有些人可能下面alloc,重新初始化空间,但这方法已给你分配了zone,自己就无需再次alloc内存空间了
// HSPerson *person = [[HSPerson alloc] init];
}
HSPerson *p = [[HSPerson alloc] init];
p.age = 20;
p.height = 170.0;
HSPerson *copyP = [p copy];
NSLog(@"p = %p copyP = %p", p, copyP);
NSLog(@"age = %d height = %f", copyP.age, copyP.height);
虽然copy了份新的对象,然而age,height值并未copy,那么:
- (id)copyWithZone:(NSZone *)zone
{
HSPerson *person = [[HSPerson allocWithZone:zone] init];
person.age = self.age;
person.height = self.height;
// 这里self其实就要被copy的那个对象,很显然要自己赋值给新对象,所以这里可以控制copy的属性
return person;
}
这时你会想,有NSMutableCopying?没错,是有这货:
- (id)mutableCopyWithZone:(NSZone *)zone
{
HSPerson *person = [[HSPerson allocWithZone:zone] init];
person.age = self.age;
person.height = self.height;
return person;
}
NSCopying、NSMutableCopying有啥区别?
其实感觉没必要有NSMutableCopying,因为压根就没可变的HSPerson,但如果该对象有其他行为,可以借用NSMutableCopying实现,哈哈哈
property里的copy、strong区别
说完深浅拷贝,理解property里的copy、strong就轻松多了!
- copy
#import <Foundation/Foundation.h>
@interface HSPerson : NSObject
@property (nonatomic, copy) NSString *name;
@end
NSMutableString *string = [NSMutableString stringWithFormat:@"汉斯哈哈哈"];
HSPerson *person = [[HSPerson alloc] init];
person.name = string;
// 不能改变person.name的值,因为其内部copy新的对象
[string appendString:@" hans"];
NSLog(@"name = %@", person.name);
property copy 实际上就对name干了这个:
- (void)setName:(NSString *)name
{
_name = [name copy];
}
假设name为NSMutableString,会发生什么事?
@property (nonatomic, copy) NSMutableString *name;
这样会挨骂哦,实际上内部还是:
- (void)setName:(NSMutableString *)name
{
_name = [name copy];
}
copy出来的仍然是不可变字符!如果有人用NSMutableString的方法,就会崩溃:
- strong
@property (nonatomic, strong) NSString *name;
NSMutableString *string = [NSMutableString stringWithFormat:@"汉斯哈哈哈"];
HSPerson *person = [[HSPerson alloc] init];
person.name = string;
// 可以改变person.name的值,因为其内部没有生成新的对象
[string appendString:@" hans"];
NSLog(@"name = %@", person.name);
文章同步到微信公众号:hans_iOS
有疑问可以在公众号里直接发
网友评论
copy 只是 mutableCopy 内存地址都变了 只有copy的内容地址没有变。
NSLog(@"---name-----%p",&name);
NSString *newname = [name copy];
NSLog(@"---newname-----%p",&newname);
打印的结果是
2017-07-29 23:13:44.332 deepCopyAndqianCopy[1785:71241] ---name-----0x7fff523639e8
2017-07-29 23:13:44.333 deepCopyAndqianCopy[1785:71241] ---newname-----0x7fff523639e0
这是为什么呢,和你的第一张截图违背了啊
NSMutableArray *element = [NSMutableArray arrayWithObject:@1];
NSMutableArray *array = [NSMutableArray arrayWithObject:element];
NSMutableArray *mutableCopyArray = [array mutableCopy];
[mutableCopyArray[0] addObject:@2];
现在我改变了 mutableCopyArray 的元素,往这个元素里加了一个 2。
现在输出 array[0] 看看,结果是 1 和 2。
你怎么解释这种结果
https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/Collections/Articles/Copying.html#//apple_ref/doc/uid/TP40010162-SW3
如果想要array和mutableCopyArray打印的数据不同,则要进行完全深拷贝,即每一层都是对象复制。
NSString *str1 = @"hehe";
NSString *str2 = [str1 copy];
NSLog(@"str1:%p str2:%p",&str1, &str2);
2016-05-30 00:35:35.916 TestCopy[19256:783473] str1:0x7fff5fbff7e8 str2:0x7fff5fbff7e0
1.NSLog(@"str1:%p str2:%p",&str1, &str2);
打印的是当前变量的地址
2.NSLog(@"str1:%p str2:%p",str1, str2);
打印的是当前变量存储的对象地址
而所谓copy NSString不会产生新对象,就是当前变量存储的对象地址没变
因为内部实现:
- (void)setName:(NSMutableString *)name
{
_name = [name copy];
}
有两个问题,第一个是用NSString、NSArray、NSDictionary来举例就是错误的,这些不可变对象是分配在静态存储区的,整个进程公用一份对象,所以无论是retain、strong,或者是深浅拷贝,对它们来说是没区别的。
第二个是,假如对象是一个容器,例如NSMutableArray。浅拷贝是拷贝容器对象本身,但是不拷贝容器内包含的元素,而深拷贝不仅仅是拷贝容器对象本身,而且还会拷贝容易内包含的对象。
无论是深浅拷贝,既然名称中都带有拷贝一词,它必然有一个拷贝的动作。而所谓的指针拷贝,就是objc中的retain/assign,跟拷贝没有半毛钱关系。
NSArray *arr1 = @[@"a"];
NSArray *arr11 = @[@"a"];
NSArray *arr2 = [arr1 copy];
NSMutableArray *arr3 = [arr1 mutableCopy];
[arr3 addObject:@[@"b"]];
NSLog(@"%p_____%p_____%p______%p",arr11,arr1,arr2,arr3);
0x608000019b90_____0x608000019b90_____0x608000019b90______0x608000044980
这个以我是用了mutableCopy 他的指针变了,不知道你说的那个没关系是怎么理解的,
感谢指出!
不会啊!
在VC里:@property (nonatomic, copy) NSString *name;
NSMutableString *string = [NSMutableString stringWithString:@"汉斯哈哈哈"];
self.name = string;
[string appendString:@" - hans"];
NSLog(@"string: %@ name: %@", string, self.name);
打印:
string: 汉斯哈哈哈 - hans name: 汉斯哈哈哈