随笔---iOS copy && strong
最近面试提到过copy和strong 这里自己写demo来巩固基础
浅拷贝:对内存地址的复制,让目标对象指针和源对象指向同一片内存空间
深拷贝:让目标对象指针和源对象指针指向亮片相同内容的内存空间,修改了原对象不会影响副本对象。
@interface ViewController ()
@property (nonatomic,strong) NSString *strongStr;
@property (nonatomic, copy) NSString *copyyStr;
@property (nonatomic, copy) NSMutableString *mutaCopyyStr;
@end
- (void)test1{
NSString *originStr1 = [NSString stringWithFormat:@"hello, everyone"];
_strongStr = originStr1;
_copyyStr = originStr1;
NSLog(@"第一种场景:用NSString直接赋值");
NSLog(@" 对象地址 对象指针地址 对象的值 ");
NSLog(@"originStr: %p , %p , %@", originStr1, &originStr1, originStr1);
NSLog(@"strongStr: %p , %p , %@", _strongStr, &_strongStr, _strongStr);
NSLog(@" copyyStr: %p , %p , %@", _copyyStr, &_copyyStr, _copyyStr);
}
strong和copy修饰的对象指向源内存地址,strong只是增加了对象的引用计数,copy只是拷贝了对象指针地址
- (void)test2{
NSMutableString *originStr1 = [NSMutableString stringWithFormat:@"hello, everyone"];
_strongStr = originStr1;
_copyyStr = originStr1;
NSLog(@"第2种场景:用NSMutableString直接赋值");
[originStr1 setString:@"hello, world"];
NSLog(@" 对象地址 对象指针地址 对象的值 ");
NSLog(@"originStr: %p , %p , %@", originStr1, &originStr1, originStr1);
NSLog(@"strongStr: %p , %p , %@", _strongStr, &_strongStr, _strongStr);
NSLog(@" copyyStr: %p , %p , %@", _copyyStr, &_copyyStr, _copyyStr);
}
copyyStr 在声明的时候用copy修饰的浅拷贝,所以源内存会有增加三个引用计数。
- (void)test3{
NSMutableString *originStr1 = [NSMutableString stringWithFormat:@"hello, everyone"];
_strongStr = originStr1;
_copyyStr = [originStr1 copy];
NSLog(@"第3种场景:用NSMutableString copy直接赋值");
[originStr1 setString:@"hello, world"];
NSLog(@" 对象地址 对象指针地址 对象的值 ");
NSLog(@"originStr: %p , %p , %@", originStr1, &originStr1, originStr1);
NSLog(@"strongStr: %p , %p , %@", _strongStr, &_strongStr, _strongStr);
NSLog(@" copyyStr: %p , %p , %@", _copyyStr, &_copyyStr, _copyyStr);
}
copyyStr所指向的对象地址和前面两个不一样,而且对象指针地址以及对象的值还是originStr1初始化的内容;NSMutableString *originStr1,
_copyyStr = [originStr1 copy]; 执行[originStr1 copy]代码之后 会在内存中开辟新的内存(深拷贝)存放originStr1初始化的内容,返回一个地址。
- (void)test4{
NSMutableString *originStr1 = [NSMutableString stringWithFormat:@"hello, everyone"];
self.strongStr = originStr1;
self.copyyStr = originStr1;
NSLog(@"第4种场景:用self. 直接赋值");
[originStr1 setString:@"hello, world"];
NSLog(@" 对象地址 对象指针地址 对象的值 ");
NSLog(@"originStr: %p , %p , %@", originStr1, &originStr1, originStr1);
NSLog(@"strongStr: %p , %p , %@", _strongStr, &_strongStr, _strongStr);
NSLog(@" copyyStr: %p , %p , %@", _copyyStr, &_copyyStr, _copyyStr);
}
self.copyyStr 会转化为setter方法,该方法内部会实现 [copyy copy]的操作 进行了深拷贝,生成一个新的对象赋值给_copyyStr。
- (void)test5{
NSString *originStr1 = [NSString stringWithFormat:@"hello, everyone"];
_mutaCopyyStr = [originStr1 copy];
NSLog(@" 对象地址 对象指针地址 对象的值 ");
NSLog(@"originStr: %p , %p , %@", originStr1, &originStr1, originStr1);
NSLog(@"originStr: %p , %p , %@", _mutaCopyyStr, &_mutaCopyyStr, _mutaCopyyStr);
}
_mutaCopyyStr 浅拷贝 ,源内存增加了引用计数。
- (void)test7{
NSMutableString *originStr1 = [NSMutableString stringWithFormat:@"hello, everyone"];
_mutaCopyyStr = [originStr1 copy];
[originStr1 setString:@"hello world"];
NSLog(@" 对象地址 对象指针地址 对象的值 ");
NSLog(@"originStr: %p , %p , %@", originStr1, &originStr1, originStr1);
NSLog(@"mutaCopyyStr: %p , %p , %@", _mutaCopyyStr, &_mutaCopyyStr, _mutaCopyyStr);
}
_mutaCopyyStr = [originStr1 copy];进行一个深拷贝,开辟新的内存空间,_mutaCopyyStr还是指向内存内容还是hello, everyone
- (void)test8{
NSString *originStr1 = [NSString stringWithFormat:@"hello, everyone"];
_mutaCopyyStr = originStr1;
[_mutaCopyyStr setString:@"4444444"];
NSLog(@" 对象地址 对象指针地址 对象的值 ");
NSLog(@"originStr: %p , %p , %@", originStr1, &originStr1, originStr1);
NSLog(@"mutaCopyyStr: %p , %p , %@", _mutaCopyyStr, &_mutaCopyyStr, _mutaCopyyStr);
}
思路:打印 _mutaCopyyStr所对应的类型 NSLog(@"_mutaCopyyStr kind===%@", NSStringFromClass([_mutaCopyyStr class]));
提示已经很明显了,尝试利用setString 来更改不可更改对象。
那么执行 [_mutaCopyyStr setString:@"4444444"]; 就会报错
如何修改呢?_mutaCopyyStr = [originStr1 mutableCopy]; 深拷贝改成可变对象;
Copy总结:
源对象类型 |
拷贝方式 |
目标对象类型 |
拷贝类型 |
NSMutableNSString |
copy |
NSSString |
深拷贝 |
NSMutableNSString |
mutableCopy |
NSMutableNSString |
深拷贝 |
NSSString |
copy |
NSSString |
浅拷贝 |
NSSString |
mutableCopy |
NSMutableNSString |
深拷贝 |
copy 修饰源对象后变成不可变对象
最后回答一道面试题
@property (nonatomic, copy) NSMutableString *mutaCopyyStr;
NSMutableString 对象 copy 修饰源对象后变成NSString类型,
那么如果赋值为一个NSMutableString 经过copy操作变成NSString 那么使用 [_mutaCopyyStr setString:@"4444444"];的时候就会报错
那么如果赋值为一个NSString 经过copy操作变成NSString 。所以为了保险起见还是用copy来修饰NSString属性 一个字安全
本文地址:https://blog.csdn.net/Coding_Physical/article/details/109251777
推荐阅读
-
IOS开发(77)之iOS高级内存管理:比较__unsafe_unretain、__strong、__weak、__autoreleasing
-
IOS开发(87)之Strong与Weak的理解
-
iOS 开发 NSString(NSDictory,NSArray)为什么用copy修饰,而不是用strong修饰
-
NSString什么时候用copy,什么时候用strong
-
iOS @property中的NSString, NSArray, NSDictionary属性为什么大多时候用copy而不用strong的原因
-
iOS block为什么要用copy
-
ios学习之真机测试 copy图片错误解决方案
-
ios开发什么情况下使用assign,copy,retain,strong,weak
-
随笔---iOS copy && strong
-
iOS开发之详谈属性设置readwrite、readonly、retain、copy、assign、nonatomic