OC语言 - 内存管理:copy | 深拷贝 | 浅拷贝 | 自定义拷贝

copy 实现原理

1 - copy 修饰属性时,其 setter/getter 方法内部实现原理同 retain 类似 

// - Person.h

#import <Foundation/Foundation.h>
@interface Person : NSObject
@property(nonatomic,copy)NSString *name;
@end

// - Person.m

复制代码
 1 #import "Person.h"
 2 @implementation Person
 3 
 4 -(void)dealloc{
 5 
 6     [_name release];
 7     NSLog(@"%@ 销毁",self);
 8     [super dealloc];
 9 }
10 
11 
12 -(void)setName:(NSString *)name{
13 
14     if (_name != name) {
15         [_name release];
16         _name = [name copy];// 不同点:使用的是 copy
17     }
18 }
19 
20 -(NSString *)getName{
21 
22     return [[_name retain] autorelease];
23 }
24 
25 @end
复制代码

深拷贝 | 浅拷贝

1 - 对不可变 NSString、NSArray、NSDictionary 等进行 copy 属浅拷贝。拷贝指针,并没有拷贝出新对象,copy 相当于是 retain

NSString *str01 = [NSString stringWithFormat:@"小白菜"];
NSLog(@"%lu   %p",[str01 retainCount],str01);//  1   0x100502850
NSString *newStr01 = [str01 copy];
NSLog(@"%lu    %p",[newStr01 retainCount],newStr01);// 2    0x100502850

2 - 对可变 NSMutableString、NSMutableArray、NSMutableDictionary 等进行 copy 是深拷贝。它会拷贝出一个新对象且新对象是不可变的

NSMutableString *str02 = [NSMutableString stringWithFormat:@"科技"];
NSLog(@"%lu %p",[str02 retainCount],str02); // 1  0x103306120
NSString *newStr02 = [str02 copy];// 返回不可变
NSLog(@"%lu %@ %p",[newStr02 retainCount],newStr02,newStr02);// 1 科技 0x103104230

3 - 对 NSString/NSMutableString、NSArray/NSMutableArray、NSDictionary/NSMutableDictionary 进行 mutableCopy 是深拷贝。会拷贝出一个新对象且新对象是可变的

1 NSString *str03 = [NSString stringWithFormat:@"小二黑结婚"];
2 NSMutableString *newSt03 = [str03 mutableCopy];// 返回可变字符串
3 NSLog(@"%p   %p",str03,newSt03);// 0x100508460   0x1005067c0
4     
5 NSMutableString *str04 = [NSMutableString stringWithFormat:@"平凡的世界"];
6 NSMutableString *newStr04 = [str04 mutableCopy];

自定义拷贝

1 - 对类进行拷贝:当一个类需要 copy 时要接受 NSCopying 协议,并且实现协议中的 copyWithZone 方法

// - Student.h

复制代码
#import <Foundation/Foundation.h>
@interface Student : NSObject<NSCopying> // 协议

@property (nonatomic,copy)NSString *name;
@property (nonatomic,copy)NSString *sex;
@property (nonatomic,assign)NSInteger  age;

- (id)initWithName:(NSString *)name sex:(NSString *)sex age:(NSInteger )age;
- (void)sayHI;

@end
复制代码

// - Student.m

复制代码
 1 #import "Student.h"
 2 @implementation Student
 3 
 4 -(void)dealloc{
 5 
 6     self.name = nil;
 7     self.sex = nil;
 8     [super dealloc];
 9 }
10 
11 - (void)sayHI{
12     NSLog(@"I am a student,name : %@,sex : %@,age : %ld",_name,_sex,_age);
13 }
14 
15 - (id)initWithName:(NSString *)name sex:(NSString *)sex age:(NSInteger )age{
16     self = [super init];
17 
18     if (self) {
19         _name = name;
20         _sex = sex;
21         _age = age;
22     }
23     return self;
24 }
25 
26 // 当一个对象 copy 时会自动调用到 copyWithZone: 方法
27 // NSZone 是用于记录原对象的内存结构信息
28 -(id)copyWithZone:(NSZone *)zone{
29 
30     // 如何实现协议中的方法
31     // 根据原对象的内存结构信息创建一个新对象
32     // 把原对象实例变量的内容复制给新对象
33     Student *newStudent = [Student allocWithZone:zone];
34     newStudent.name = self.name;
35     newStudent.sex = self.sex;
36     newStudent.age = self.age;
37 
38     return newStudent;
39 }
40 
41 @end
复制代码

// - main.m

复制代码
 1 #import <Foundation/Foundation.h>
 2 #import "Student.h"
 3 
 4 int main(int argc, const char * argv[]) {
 5 
 6     Student *stu01 = [[Student alloc] initWithName:@"Bruce" sex:@"male" age:17];
 7     NSLog(@"%@===%@ %@ %ld",stu01,stu01.name,stu01.sex,stu01.age);// <Student: 0x101dafb80>===Bruce male 17
 8     NSLog(@"%lu",[stu01 retainCount]);// 1
 9 
10     // copy 会拷贝出一份新的对象
11     Student *newstudent = [stu01 copy];
12     // newstudent 和 stu01 地址不一样
13     NSLog(@"%@===%@ %@ %ld",newstudent,newstudent.name,newstudent.sex,newstudent.age);//  <Student: 0x104904320> Bruce male 17
14     NSLog(@"stu04---%lu  newstudent---%lu ",[stu01 retainCount],[newstudent retainCount]);// stu01---1  newstudent---1
15 
16     Student *newstudentII = [newstudent copy];
17     NSLog(@"newstudent---%lu  newstudentII---%lu ",[newstudent retainCount],[newstudentII retainCount]);//  newstudent---1  newstudentII---1
18 
19     return 0;
20 }
复制代码

小结

1 - copy 修饰的属性仅限于 NSString、NSArray、NSDictionary,也是苹果推荐的使用方式

2 - 对于 NSMutableArray、NSMutableString、NSMutableDictionary 等可变因素一旦 copy 后就会生成一个不可变的对象,这在实际开发中是我们不想看到的

// - Person.h

#import <Foundation/Foundation.h>
@interface Person : NSObject
@property(copy,nonatomic)NSMutableArray *mutArray;

@end

// - main.m

复制代码
 1 #import <Foundation/Foundation.h>
 2 #import "Person.h"
 3 int main(int argc, const char * argv[]) {
 4 
 5     Person *p = [Person new];
 6     
 7     NSMutableArray *array01 = [NSMutableArray arrayWithCapacity:1];
 8     p.mutArray = array01;
 9     [p.mutArray addObject:@"5"];// crash
10     
11     // 因为属性 mutArray 是 copy 修饰的
12     // 经过点语法赋值之后 p.mutArray 拿到的是新拷贝出的不可变数组
13     // 不可变数组调用了一个并不存在的方法 addObject,故 crash
14 
15     return 0;
16 
17 }
复制代码

 

posted on   低头捡石頭  阅读(35)  评论(0编辑  收藏  举报

编辑推荐:
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

导航

统计

点击右上角即可分享
微信分享提示