深拷贝和浅拷贝的区别:
- 浅拷贝就是拷贝后,并没有进行真正的复制,而是复制的对象和原对象都指向同一个地址
- 深拷贝是真正的复制了一份,复制的对象指向了新的地址
从上图可以看出,浅拷贝A指针改变了所指向的内容B指针也指向被修改后的内容。如果有些地方用到B指针,不希望在A指向的内容发生变化时也跟着变化,则需要用到深拷贝。可得出结论:
深拷贝 : 拷贝出来的对象与源对象地址不一致! 这意味着我修改拷贝对象的值对源对象的值没有任何影响.
浅拷贝 : 拷贝出来的对象与源对象地址一致! 这意味着我修改拷贝对象的值会直接影响到源对象.
copy和mutaleCopy的区别:
- 拷贝的对象主要分以下四种
- 非容器不可变对象:NSString
- 非容器可变对象: NSMutableString
- 容器类不可变对象: NSArray、NSDictionary等
- 容器类可变对象: NSMutableArray、NSMutableDictionary等
- copy和mutableCopy对不同对象拷贝的结果:
copy关键字的使用:
在iOS开发中,一般使用copy修饰的属性有NSString、NSArray、NSDictionary。
- 为什么上述属性需要使用copy修饰呢?
原因是上述属性都有可变的子类,如 NSString->NSMutableString、NSArray->NSMutableArray、NSDictionary->NSMutableDictionary;根据面相对象的多态特性,NSString类型的变量可以指向NSMutableString类型的变量。声明对象的属性一般都是希望明确知道对象的值,但是如果对子类是可变类型的属性使用strong修饰的话,可能会在对象不知情的情况下修改对象属性的值。
测试代码如下:
@interface Test : NSObject
@property (nonatomic,strong) NSString * testStr ;
+ (void)logCopyTest;
@end
--------------.m--------------
#import "Test.h"
@implementation Test
+ (void)logCopyTest {
Test *testM = [[Test alloc] init];
NSMutableString *test1 = [[NSMutableString alloc] initWithString:@"str"];
testM.testStr = test1;
NSLog(@"testStr = %p value = %@", testM.testStr, testM.testStr);
[test1 appendString:@"add"];
NSLog(@"testStr = %p value = %@", testM.testStr, testM.testStr);
test1.string = @"333";
NSLog(@"testStr = %p value = %@", testM.testStr, testM.testStr);
}
-------------调用-------------
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
[Test logCopyTest];
}
打印结果如下:
可以看到用strong修改的testStr属性的值,随着test1值的改变而改变。
如果把strong修改成copy后:
@interface Test : NSObject
@property (nonatomic,copy) NSString * testStr ;
+ (void)logCopyTest;
@end
打印的结果如下:
可以看出copy修改的属性值没有根据test1的值改变。
从上面的示例中,可以了解,属性的修饰符是使用copy还是strong,取决于修改的类型是否要根据引用的值的改变而改变。