900字范文,内容丰富有趣,生活中的好帮手!
900字范文 > Objective-C 深复制和浅复制与NSCopying协议

Objective-C 深复制和浅复制与NSCopying协议

时间:2018-08-20 22:16:32

相关推荐

Objective-C 深复制和浅复制与NSCopying协议

1.简单复制只能实现浅拷贝:指针赋值,使两个指针指向相同的一块内存空间,操作不安全。

2. Foundation类已经遵守了<NSCopying>和 <NSMutableCopying>协议,即实现了copy和mutableCopy方法,因此Foundation对象可以使用这些方法创建对象的副本或可变副本

@protocol NSCopying

- (id)copyWithZone:(NSZone *)zone;

@end

@protocol NSMutableCopying

- (id)mutableCopyWithZone:(NSZone *)zone;

@end

3.用户自定义类遵守<NSCopying>协议和<NSMutableCopying>协议,则必须实现copyWithZone方法和mutableCopyWithZone方法,否则该类对象无法响应copy和mutableCopy消息

4.实现copyWithZone方法,例:

-(id)copyWithZone:(NSZone *)zone

{

Student *stu = [[StudentallocWithZone:zone]initWithName:self.nameAge:self.age];

return stu;

}

对应main函数中:假设已经有一个Student对象stu1;

则:Student stu2 = [stu1 copy];

实现stu2是stu1的副本,这里是深复制,stu1和stu2分别对应不同内存。

5. 如果你的类产生了子类,那么copyWithZone:方法也将

被继承

Student *stu = [[Student allocWithZone: zone] init];

该方法应该改为: Student *stu =[[[self class]allocWithZone: zone]init];

如果编写一个类的copyWithZone:方法那么子类的方法应该先调用父类的copy方法以复制继承来的copy实例变量.

1 NSCopying与NSMutableCopying协议

用copy方法能得到字符串的不可变副本,而mutableCopy方法能得到字符串的可变副本。

但是如果对自定义的类,我们不能直接使用copy和mutableCopy方法,需要让类遵守NSCopying与NSMutableCopying协议,然后实现继承自协议的copyWithZone:方法和mutableCopyWithZone:方法,这两个方法返回的是对象本身,得到一个对象的副本。

总之,为了保证一个自定义的类的对象使用copy方法产生一个不可变的副本,需要做两步:

1. 让该类继承NSCopying协议。

2. 在类的代码实现部分重写继承自NSCopying协议的CopyWithZone:方法,该方法返回一个该类的不可变对象副本。

为了保证一个自定义的类的对象使用mutableCopy方法产生一个可变的副本,需要做两步:

1. 让该类继承NSMutableCopying协议。

2. 在类的代码实现部分重写继承自NSMutableCopying协议的mutableCopyWithZone:方法,该方法返回一个该类的可变对象副本。

2 深复制和浅复制

代码示例如下:

GKHUser.h

[code]#import <Foundation/Foundation.h>//继承NSCopying和NSMutableCopying协议@interface GKHUser : NSObject <NSCopying, NSMutableCopying>@property (nonatomic, strong) NSMutableString *name;//类似retain类型,引用计数@property (nonatomic, assign) int age;@end

GKHUser.m

[code]#import "GKHUser.h"@implementation GKHUser//重写copyWithZone:方法- (id) copyWithZone:(NSZone *)zone {NSLog(@"执行copyWithZone:方法");//使用zone参数创建一个GKHUser对象GKHUser *user = [[[self class] allocWithZone:zone] init];user.name = self.name;//这里只是浅复制user.age = self.age;return user;}//重写mutableCopyWithZone:方法- (id) mutableCopyWithZone:(NSZone *)zone {NSLog(@"执行mutableCopyWithZone:方法");//使用zone参数创建一个GKHUser对象GKHUser *user = [[[self class] allocWithZone:zone] init];user.name = self.name;//这里只是浅复制user.age = self.age;return user;}@end

main.m

[code]#import <Foundation/Foundation.h>#import "GKHUser.h"int main(int argc, const char * argv[]) {@autoreleasepool {GKHUser *user1 = [GKHUser new];user1.name = [NSMutableString stringWithString:@"李太"];user1.age = 10;GKHUser *user2 = [user1 copy];//复制不可变副本[user1.name appendString:@"白"];user2.age = 20;NSLog(@"user1的名字为:%@", user1.name);NSLog(@"user1的年龄为:%d", user1.age);NSLog(@"user2的名字为:%@", user2.name);NSLog(@"user2的年龄为:%d", user2.age);GKHUser *user3 = [GKHUser new];user3.name = [NSMutableString stringWithString:@"张大"];user3.age = 30;GKHUser *user4 = [user3 mutableCopy];//复制可变副本[user3.name appendString:@"彪"];user4.age = 40;NSLog(@"user3的名字为:%@", user3.name);NSLog(@"user3的年龄为:%d", user3.age);NSLog(@"user4的名字为:%@", user4.name);NSLog(@"user4的年龄为:%d", user4.age);}return 0;}

运行main.m结果:

执行copyWithZone:方法

user1的名字为:李太白

user1的年龄为:10

user2的名字为:李太白

user2的年龄为:20

执行mutableCopyWithZone:方法

user3的名字为:张大彪

user3的年龄为:30

user4的名字为:张大彪

user4的年龄为:40

我们从结果中发现,不管是可变复制还是不可变复制,最后修改副本的name属性时候,会导致原始对象的属性也发生修改,为什么呢?因为这里的copyWithZone:和mutableWithZone:方法中对name属性的赋值是浅复制,如下图:

为了达到我们的效果,GKHUser.h和main.m代码不变,而GKHUser.m修改如下:

GKHUser.m

[code]#import "GKHUser.h"@implementation GKHUser//重写copyWithZone:方法- (id) copyWithZone:(NSZone *)zone {NSLog(@"执行copyWithZone:方法");//使用zone参数创建一个GKHUser对象GKHUser *user = [[[self class] allocWithZone:zone] init];user.name = [self.name copy];//这里对name指向的对象执行深复制,复制的副本为不可变的字符串user.age = self.age;return user;}//重写mutableCopyWithZone:方法- (id) mutableCopyWithZone:(NSZone *)zone {NSLog(@"执行mutableCopyWithZone:方法");//使用zone参数创建一个GKHUser对象GKHUser *user = [[[self class] allocWithZone:zone] init];user.name = [self.name mutableCopy];//这里对name指向的对象执行深复制,复制的副本为可变的字符串user.age = self.age;return user;}@end

运行main.m结果:

执行copyWithZone:方法

user1的名字为:李太白

user1的年龄为:10

user2的名字为:李太

user2的年龄为:20

执行mutableCopyWithZone:方法

user3的名字为:张大彪

user3的年龄为:30

user4的名字为:张大

user4的年龄为:40

这样就达到了我们的目的,user2是user1的不可变副本,实现了copy方法,而user4是user3的可变副本,实现了mutableCopy方法。

其在内存中的示意图如下:

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。