// 第九章 内存管理(初级)
// 一、ios应用程序造成的Crash的主要原因就是内存问题, 内存问题分两种:
// (1)、内存溢出:
// (2)、野指针异常: 对象内存空间已经被系统回收, 仍然使用指针操作这块内存(crash的主要原因)
// 二、常见的内存管理方式有: GC、MRC、ARC:
// (1)、GC: java采用的内存管理方式
// 垃圾回收机制: 由程序员开辟空间, 不需要用代码释放, 系统判断空间哪些内存不在被使用, 并回收这些内存 每次释放需要4 - 8倍的空闲内存;
// (2)、IOS采用的是引用计数: 引用计数就是来标记当前使用的个数
// 分为 MRC 人工引用计数(对内存的控制更加灵活, 对程序员要求比较高)
// ARC(基于MRC) 自动引用计数(编译器帮程序员默认加了释放的代码)
// 三、引用计数, 记录某块内存有几个引用(0时对象释放所占的资源)
//影响引用计数的方法:
// (1)alloc retain copy 引用计数加1
// (2)release autorelease 引用计数减1
// alloc
Person *per = [[Person alloc]init];//alloc使引用计数加1
NSLog(@"per的引用计数: %lu", per.retainCount);
//从引用计数的角度: alloc 是引用计数 从 0 到 1
//从对象的角度: 对象从无到有的过程
// retain
Person *per1;
[per1 retain];//没有对象 相当于[nil retain]
NSLog(@"per1的引用计数: %lu", per1.retainCount);//奔溃, 并没有分配内训空间
//此时per 和 per2 指向的是同一块内存空间
Person *per2 = [per retain];//引用计数加1
NSLog(@"per 的引用计数: %lu", per.retainCount);
NSLog(@"per2 的引用计数: %lu", per2.retainCount);
// copy
//基本上对象类型都有<NSCopying>
Person *per3 = [per copy];//程序奔溃, 自动调用 copyWithZone
//遵守NSCopying 协议 的对象才能Copy
NSLog(@"per 的引用计数: %lu, per3 的引用计数:%lu",per1.retainCount, per3.retainCount);
NSArray *arr = @[@"1", @"2", @"3"];
NSLog(@"arr 的引用计数: %lu", arr.retainCount);//1
NSLog(@"%p", arr);
NSArray *arr1 = [arr copy];
NSLog(@"arr1 的引用计数: %lu", arr1.retainCount);
NSLog(@"%p , %p", arr, arr1);
[per release];//引用计数减1
NSLog(@"per 的引用计数: %lu",per.retainCount);
//引用计数为1的时候再次进行release系统就会回收这块内存, 但是打印引用计数仍为1
[per2 release];
NSLog(@"per2 的阴影计数: %lu",per2.retainCount);//此时per2 指向的内存已经被回收, 再获取引用计数已经没有意义
// 四、内存管理的原则:
// (1). 有加就有减 看到alloc retain copy 就要在合适的地方进行release
// (2). 谁引起引用计数的增加, 就由谁来进行release
//autorelease
{
//在未来的某个时刻让引用计数 -1, 指的是出自动释放池(autoreleasepool)
Person *per = [[Person alloc]init];
[per retain];
[per retain];
//(1) NSAutoreleasepool
NSAutoreleasePool *autoRepopl = [[NSAutoreleasePool alloc]init];
//autorelease并不会引起引用计数的变化
[per autorelease];//出现在两种之间, 相当于先进后出, 进出栈
NSLog(@"per 的引用计数: %lu",per.retainCount);
[autoRepopl release];//此时 autorelease 的对象引用计数 - 1
NSLog(@"per - 1 的引用计数: %lu",per.retainCount);
//(2) @autoreleasepool 代码块
@autoreleasepool {
[per autorelease];
NSLog(@"per 的引用计数:%lu", per.retainCount);
}//出代码块时 autorelease 的对象引用计数 - 1 自动释放池向各对象发送release信息
NSLog(@"per - 2 的引用计数:%lu", per.retainCount);
[per release];
//[per autorelease];
}
// 五、dealloc
// 内部实现方法: 引用计数由1变成0的时候, 系统会自动调用本方法, 来回收内存, 不需要手动调用
-(void)dealloc{
[super dealloc];
}
//由于dealloc方法是重写的父类,所以重写此方法的时候,一定要把父类的方法内容也写上
// 六、Copy
// 分类 (1)copy、mutableCpoy
// (2)不可变数组 可变数组
// (3)浅拷贝: 相当于retain, 仅仅是让引用计数 + 1,并未开辟新的内存空间
// 深拷贝: 重新开辟一块新的空间, 将拷贝的对象的内容复制到这块空间中, 产生一个新的对象
// 1.不可变copy去拷贝不可变数组 浅拷贝 相当于retain;
{
NSArray *arr = @[@"sfew",@"sfawe",@"ryh"];
NSArray *arrCopy = [arr copy];
NSLog(@"%lu %lu",arr.retainCount,arrCopy.retainCount);
NSLog(@"%p %p",arr,arrCopy);
NSLog(@"%@",[arrCopy class]);
}
// 2.不可变copy去拷贝可变数组 深拷贝
{
NSMutableArray *arr = @[@"长得好看有什么用", @"他学习又不好"].mutableCopy;
NSMutableArray *arr1 = [NSMutableArray arrayWithObjects:@"嘿嘿嘿", @"呵呵呵", nil];
NSMutableArray *arrcopy = arr1.copy;
//拷贝的返回值跟拷贝的对象没有关系, 而是取决于copy本身, 如果是不可变copy返回值是不可变的, 如果是mutableCopy,返回值就是可变的
NSLog(@"arr1 引用计数: %lu, arrcopy 引用计数: %lu",arr1.retainCount, arrcopy.retainCount);
NSLog(@"%p, %p", arr1, arrcopy);
// [arrcopy addObject:@"我就呵呵呵呵"];arrcopy本质是不可变数组, 错误写法
NSLog(@"%@",[arrcopy class]);//打印arrcopy的类型
}
// 3.可变的Copy拷贝不可变的数组 深拷贝
{
NSArray *arr = @[@"aregr",@"EFW"];
NSMutableArray *MARR = [arr mutableCopy];
NSLog(@"%lu %lu",arr.retainCount,MARR.retainCount);
NSLog(@"%@",[MARR class]);
if ([MARR isKindOfClass:[NSMutableArray class]]) {
NSLog(@"可变数组");//这里不能判断是否是 不可变类型, 因为可变继承不可变
}
}
// 4.可变的Copy拷贝可变的数组 深拷贝
{
NSMutableArray *mArr = [NSMutableArray arrayWithObjects:@"farwg",@"arwg", nil];
NSMutableArray *Marr = mArr.mutableCopy;
NSLog(@"%lu %lu",mArr.retainCount,Marr.retainCount);
NSLog(@"%@",[Marr class]);
}
// 自定义类的Copy
{
Person *per = [[Person alloc]init];
per.name = @"awrg";
per.hobby = @"agdsv";
Person *perCopy = per.copy;
NSLog(@"%@ %@",perCopy.name,perCopy.hobby);
[per release];
[perCopy release];
}
//自定义的mutableCopy
{
Person *per = [[Person alloc]init];
per.name = @"awrg";
per.hobby = @"agdsv";
Person *perCopy1 = [per mutableCopy];
NSLog(@"%@ %@",perCopy1.name,perCopy1.hobby);
[per release];
[perCopy1 release];
}
//浅拷贝的实现
-(id)copyWithZone:(NSZone *)zone{
return [self retain];//浅拷贝
}
//深拷贝的实现
-(id)mutableCopyWithZone:(NSZone *)zone{
Person *per = [[Person alloc]init];
per.name = self.name;
per.age = self.age;
return per;
}
OC - 第九章 内存管理( 初级 )
最新推荐文章于 2016-10-19 16:59:14 发布