iOS 深拷贝、浅拷贝(1)非容器类对象实例

来源:互联网 发布:西安市爱知中学官网 编辑:程序博客网 时间:2024/06/01 10:09


对象的复制就是复制一个对象作为副本,它会开辟一块新的内存(退内存)来存储副本对象,即源对象和副本对象是两块不同的内存区域,对象要具备复制功能,必须实现<NSCopying>协议或者<NSMutableCopying>协议,常用的可复制对象有:NSNumber、NSString、NSMutableString、NSArray、NSMutableArray、NSDictionary、NSMutableDictionary。自定义的对象要具有可复制性也要实现<NSCopying>协议或者<NSMutableCopying>协议,并实现该协议的 copyWithZone:方法活mutableCopyWithZone:方法。

copy方法:产生对象的副本是不可变的。

mutableCopy方法:产生对象的副本是可变的。

举个例子:

    NSString *str = @"哈哈";    // 没有产生新对象    NSString *copyStr = [str copy];    // 产生新对象    NSMutableString *mutableCopyStr = [str mutableCopy];    NSLog(@"\n str = %p\n copyStr = %p\n mutableCopyStr = %p", str, copyStr, mutableCopyStr);        NSMutableString *string = [NSMutableString stringWithString:@"呵呵"];    // 产生新对象    NSString *copyString = [string copy];    // 产生新对象    NSMutableString *mutableCopyString = [string mutableCopy];    NSLog(@"\n string = %p\n copyString = %p\n mutableCopyString = %p", string, copyString, mutableCopyString);

结果如下:

可以发现 只有在一种情况下才不会产生新对象地址。

什么是浅拷贝,什么是深拷贝?

浅拷贝:浅拷贝只复制对象本身,对象里的属性、包含的对象不做复制。属于指针拷贝,使原对象的引用计数+1,可以理解为创建了一个指向原对象的新指针而已,并没有创建一个全新的对象,不会产生新对象地址。

深拷贝:既复制对象本身,对象的属性也会复制一份。属于内容拷贝,会产生内存地址完全不一样的新的对象,创建后和原对象没有任何关系

举个例子:

新建一个Person类。实现<NSCopying>协议,实现copyWithZone:方法。

@interface Person : NSObject<NSCopying>@property (nonatomic, assign) NSInteger age;@property (nonatomic, assign) NSInteger height;@property (nonatomic, strong) NSString *name;@end

@implementation Person-(id)copyWithZone:(NSZone *)zone{    Person *p = [[Person allocWithZone:zone] init];    return p;}@end

实例化该类,并copy对象:

    Person *p = [[Person alloc] init];    p.age = 18;    p.height = 175;    p.name = @"abc";    Person *copyP = [p copy];    NSLog(@"\n p = %p\n copyP =%p",p,copyP);    NSLog(@"\n name = %@\n age = %ld\n height = %ld",copyP.name,copyP.age,copyP.height);
运行结果:


虽然copy了份新的对象,然而age,height,name值并未copy。那么咱们在在copyWithZone:方法中,对属性进行赋值即可:

-(id)copyWithZone:(NSZone *)zone{    Person *p = [[Person allocWithZone:zone] init];    p.age = self.age;    p.height = self.height;    p.name = self.name;    return p;}

再运行,得到结果:


再说说property里的copy、strong,改一点代码:

    NSMutableString *name = [NSMutableString stringWithFormat:@"abc"];    Person *p = [[Person alloc] init];    p.age = 18;    p.height = 175;//    p.name = @"abc";    p.name = name;    Person *copyP = [p copy];        [name appendString: @"123"];        NSLog(@"\n name = %@\n age = %ld\n height = %ld",copyP.name,copyP.age,copyP.height);
运行结果如果:


如果将name的修饰词用copy代替strong之后运行打印出来的p.name是abc,就不贴运行图了。name appendString:未能改变name的值,因为其内部copy新的对象,property copy 实际上就对name干了这个:

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

而这里传入的name刚好是NSMutableString,所以产生了新的对象地址,所以再改变原name的值并不能影响Person中的name。


以上是对非容器类对象的举例。

阅读全文
0 0
原创粉丝点击