1.NSString
先看NSString的深浅拷贝
NSString * string = @"hello world";
/** 浅拷贝 */
NSString * copyString = [string copy];
/** 深拷贝 */
NSMutableString * mutableCopyString = [string mutableCopy];
NSLog(@"\nstring = %p\ncopyString = %p\nmutableCopyString = %p",string,copyString,mutableCopyString);
输出结果为:
string = 0x104cae7d0
copyString = 0x104cae7d0
mutableCopyString = 0x7fa400f04fd0
由此看出NSString中
- 浅拷贝:未产生新对象
- 深拷贝:产生新对象
2.NSSMutableString
再看NSSMutableString的深浅拷贝
NSMutableString * mString = [NSMutableString stringWithString:@"hello world"];
/** 浅拷贝 */
NSString * copyMString = [mString copy];
/** 深拷贝 */
NSMutableString * mutableCopyMString = [mString mutableCopy];
NSLog(@"\nmString = %p\ncopyMString = %p\nmutableCopyMString = %p",mString,copyMString,mutableCopyMString);
输出结果为:
mString = 0x7ffe42467130
copyMString = 0x7ffe42473b90
mutableCopyMString = 0x7ffe42402a50
由此看出NSSMutableString中
- 浅拷贝:产生新对象
- 深拷贝:产生新对象
备注
NSString中,stringWithString已被弃用,直接更改为赋值
NSMutableString中,只可用stringWithString或stringWithFormat,而无法直接赋值
在OC中,stringWithFormat会新申请一片空间并初始化字符串,所以每一个用stringWithFormat方法得到的字符串其指针都是不相同的。
而stringWithString是通过浅拷贝的方式得到字符串,浅拷贝只拷贝指针不拷贝对象,因此指针与内容相同。
另外
快速初始化(initWithString)是首先根据一定的方法(此方法和NSSet(集合)中的存放对象的方法一样都是hash算法)在内存中查找是否已经存在了这样的一个对象,若是存在则放回此对象的指针,若不存在,则根据一定的方法找到一片内存空间存放对象,并返回指针。
3.以下原理相同
NSArray;
NSMutableArray;
NS*;
NSMutable*;
即:
源对象类型 | 拷贝方法 | 副本对象类型 | 是否产生了新对象 | 拷贝类型 |
---|---|---|---|---|
NSString | copy | NSString | NO | 浅拷贝(指针拷贝) |
mutableCopy | NSMutableString | YES | 深拷贝(内容拷贝) | |
NSMutableString | copy | NSString | YES | 深拷贝(内容拷贝) |
mutableCopy | NSMutableString | YES | 深拷贝(内容拷贝) | |
NSArray | copy | NSArray | NO | 浅拷贝(指针拷贝) |
mutableCopy | NSMutableArray | YES | 深拷贝(内容拷贝) | |
NSMutableArray | copy | NSArray | YES | 深拷贝(内容拷贝) |
mutableCopy | NSMutableArray | YES | 深拷贝(内容拷贝) | |
NS* | copy | NS* | NO | 浅拷贝(指针拷贝) |
mutableCopy | NSMutable* | YES | 深拷贝(内容拷贝) | |
NSMutable* | copy | NS* | YES | 深拷贝(内容拷贝) |
mutableCopy | NSMutable* | YES | 深拷贝(内容拷贝) |
4.copy NSObject
看个例子
YWMPerson * person = [[person alloc] init];
person.age = 20;
person.height = 170.0;
YWMPerson * copyPerson = [person copy]; // 这里崩溃
根据崩溃的信息,应实现:
- (id)copyWithZone:(NSZone *)zone;
则:
#import "YWMPerson.h"
@interface YWMPerson()
@end
@implementation YWMPerson
- (id)copyWithZone:(NSZone *)zone
{
return @"hello world";
}
@end
YWMPerson * person = [[YWMPerson alloc] init];
person.age = 20;
person.height = 170.0;
YWMPerson *copyPerson = [person copy];
NSLog(@"copyPerson: %@", copyPerson);
输出结果为:
copyPerson: hello world
可以看出copyWithZone重新分配新的内存空间,则:
- (id)copyWithZone:(NSZone *)zone
{
YWMPerson * person = [[YWMPerson allocWithZone:zone] init];
return person;
// 有些人可能下面alloc,重新初始化空间,但这方法已给你分配了zone,自己就无需再次alloc内存空间了
// YWMPerson * person = [[YWMPerson alloc] init];
}
YWMPerson * person = [[YWMPerson alloc] init];
person.age = 20;
person.height = 170.0;
YWMPerson * copyPerson = [person copy];
NSLog(@"person = %p copyPerson = %p", person, copyPerson);
NSLog(@"age = %d height = %f", copyPerson.age, copyPerson.height);
然而结果却是age与height均为0,虽然copy了份新的对象,然而age,height值并未copy,那么:
- (id)copyWithZone:(NSZone *)zone
{
YWMPerson *person = [[YWMPerson allocWithZone:zone] init];
person.age = self.age;
person.height = self.height;
// 这里self其实就要被copy的那个对象,很显然要自己赋值给新对象,所以这里可以控制copy的属性
return person;
}
OK,copy成功!
其实还有NSMutableCopying
- (id)mutableCopyWithZone:(NSZone *)zone{
//原理与-(id)copyWithZone:(NSZone *)zone相同
}
其实没必要有NSMutableCopying,因为YWMPerson不可变,但如果该对象有其他行为,可以借用NSMutableCopying实现
5.copy与strong
最后是copy与strong
@interface YWMPerson : NSObject
@property (nonatomic,copy)NSString * nameCopyString;
@property (nonatomic,copy)NSMutableString * nameCopyMString;
@end
NSMutableString * mmString = [NSMutableString stringWithFormat:@"string"];
YWMPerson * person = [[YWMPerson alloc]init];
person.nameCopyString = mmString;
person.nameStrong = mmString;
[mmString appendString:@"+++string"];
NSLog(@"name = %@",person.nameCopyString);
NSLog(@"name = %@",person.nameStrong);
输出结果是:
name = string
name = string+++string
看了结果你一定秒懂
- copy不能改变person.nameCopyString的值,因为其内部copy新的对象
- strong可以改变person.nameStrong的值,因为其内部没有生成新的对象
property copy 实际上就对nameCopyString干了这个:
- (void)setNameCopyString:(NSString *)nameCopyString
{
_nameCopyString = [nameCopyString copy];
}
如果你说我想这样用:
@property (nonatomic,copy)NSMutableString * nameCopyMString;
这回崩了,为啥?因为系统还是这么跑的:
- (void)setNameCopyMString:(NSMutableString *)nameCopyMString
{
_nameCopyMString = [nameCopyMString copy];
}
copy出来的仍然是不可变字符!如果有人用NSMutableString的方法,就会崩溃。