您的位置:首页 > 运维架构

内存管理、copy、深浅拷贝

2015-08-12 16:55 465 查看
内存管理、copy、深浅拷贝
一、内存管理
1.内存管理的核心:谁分配、谁释放。
2.引用计数器加1的有:alloc、new、copy、retain。
3.引用计数器减1的有:release、autorelease。
注意:有retain就有release。
4.延迟释放(autorelease):和自动释放池配合使用,写在自动释放池生命周期以内。
1)在什么时候可以使用延迟释放?
带有延迟释放的对象。如传递参数。在释放池生命周期结束之后释放。
示例:
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];//初始化自动释放池
Person *huLuWa = [[[Person alloc]init]autorelease];
[pool release];
5.变量的生命周期
1)局部变量的生命周期
从定义位置开始到定义位置存在的括号以内。
2)全局变量的生命周期
对象只要存在全局变量就可以使用。
6.系统中需要管理内存数据和系统中不需要管理内存的数据
1)不需要管理内存的数据(系统管理)
分配在栈里面的数据(基本数据类型)。
2)需要管理内存的数据
分配在堆里面的。
7.setter、getter方法的内存管理
1)除了基本数据类型都有retain。
2)非原子性(nonatomic):在多线程的情况下不保证在不同线程数据的安全。
3)原子性(atomic) :在多线程里面保证数据的安全。

4)只要不使用多线程就用 nonatomic。
@property (nonatomic, retain) NSMutableArray *list;
5)基本数据类型使用assign
@property (nonatomic, assign) int age;

8.ARC情况下
1)如果这个对象在内存不足的时候,允许它被销毁掉。我们用 unsafe_unretained。
2)如果这个对象在内存不足的时候,不允许它被销毁掉。我们用 strong。
@property (nonatomic, unsafe_unretained) Dog *name;
@property (nonatomic, strong) Dog* age1;

二、copy
1.copy:会生成一个新的对象。给新的对象引用计数+1。
2.copy与retain的区别
1)retain只会给原来的对象引用计数+1,不会生成新的对象。
2)copy会生成一个新的对象。给新的对象引用计数+1。
3.如何实现
Person *p = [[Person alloc]init];
Person *p1 = [p copy];
[p1 release];
[p release];
在Person.m中需要自定义拷贝功能
- (id)copyWithZone:(NSZone *)zone{
Person *对象名 = [[Person allocWithZone:zone]init];
对象名.属性名 = self.属性名;
对象名.属性名 = self.属性名;
….
return 对象名;
}

3.自定义拷贝:除了字符串、数组、字典和NSNumber,其他的都需要自定义拷贝的功能 (遵守拷贝协议)。

三、深浅拷贝
1.深拷贝:完全拷贝一个对象。和原来的对象完全是两个个体。
2.浅拷贝:只拷贝对象本身,不拷贝对象里面的内容。
3.判断深浅拷贝的依据?
看它们(不止对象本身 ,也包含对象里面的具体的内容)的内存地址是否一样。
4.浅拷贝
Person *p =[[Person alloc]init];
NSArray *array = [NSArray arrayWithObject:p];
NSArray *array1 = [array copy];
NSLog(@"拷贝之前: %p", array[0]);
NSLog(@"拷贝之后: %p", array1[0]);
注意:copy mutableCopy 系统默认的是浅拷贝。
5.深拷贝
1)自定义的mutableCopy拷贝 深拷贝
- (id)mutableCopyWithZone:(NSZone *)zone{
Person *mutableCopyPer = [[Person allocWithZone:zone]init];
// 如果使用copy会把可变数组 变成不可变数组
mutableCopyPer.list = [self.list mutableCopy];
mutableCopyPer.age = self.age;
return mutableCopyPer;
}

示例:Person *p1 = [p mutableCopy];
NSLog(@"深拷贝之前: %p", p);
NSLog(@"深拷贝之后: %p", p1);
2)数组的深拷贝(不需要自定义mutableCopy,因为数组里面已经有深拷贝的协议)
NSArray *array2 = [[NSArray alloc]initWithArray:array copyItems:YES];
设置成YES就是深拷贝
NSLog(@"深拷贝之前: %p", array[0]);
NSLog(@"深拷贝之后: %p", array2[0]);

3)字典深拷贝
NSDictionary *dic = @{@"key":p};
NSDictionary *dic1 = [[NSDictionary alloc]initWithDictionary:dic copyItems:YES];
设置成YES就是深拷贝
NSLog(@"字典拷贝之前: %p", dic[@"key"]);
NSLog(@"字典拷贝之后: %p", dic1[@"key"]);

4)深拷贝的其他方式
sqlite3、coreDara、 plist、 归档和文件操作。
6. 如果想让一个不可变对象变成一个可变对象 可以使用mutableCopy
NSArray *list = @[@"1", @"2", @"3"];
NSMutableArray *rec = [list mutableCopy];
[ rec removeLastObject];
NSLog(@"%@", rec);

7.如果对一个可变的对象进行 copy 它将变成一个不可变的对象,所以不能使用copy 必须使用mutableCopy。
NSMutableString *string = [NSMutableString stringWithString:@"abcdef"];
注意:NSMutableString *recString = [string copy];这里不能使用copy 必须使用mutableCopy
NSMutableString *recString = [string mutableCopy];
如果使用了copy,运行之后系统将会报以下错误
reason: '-[NSTaggedPointerString appendString:]: unrecognized selector sent to instance

[recString appendString:@"ghi"];
NSLog(@"%@", recString);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: