1.OC内存管理函数
1)范围:管理任何继承NSObject的对象,对其余的基本数据类型无效(堆区),不然会形成内存泄露atom
2)原理:任何对象均可能有用一个或多个全部者,只要一个对象至少还拥有一个全部者,它就会继续存在spa
3)对象的引用计数器,retain(+1)、release(-1)、retainCount获得引用计数器的值3d
4)内存管理的分类:MRC(手动管理)、ARC(自动管理)、垃圾回收(不支持)指针
2.引用计数器的使用code
dealloc:释放对象对象
先调用[super dealloc]blog
咱们建立一个项目,默认是ARC模式,先修改继承
//
// main.m // 内存管理 //
// Created by fanyafang on 15/11/6. // Copyright © 2015年 itcast. All rights reserved. //
#import <Foundation/Foundation.h>
#import "Person.h"
int main(int argc, const char * argv[]) { @autoreleasepool { Person *p =[[Person alloc]init]; NSUInteger count=[p retainCount]; NSLog(@"%lu",count); //Person *p2=p;//不变 //Person *p2=[p retain];//加1
[p retain];//加1
[p release];//减一
[p release];//减一自动调用dealloc方法 //证实p的空间被释放,能够在Person类中重写dealloc方法
} return 0; }
3.内存管理的原则ip
1)只要有人使用这个对象,这个对象就不会被回收
2)只要你想使用这个对象,那么就应该让这个对象的引用计数器加1
3)当你不想使用这个对象时,应该让对象的引用计数器减1
4)谁建立(new、malloc、copy)谁release
5)谁retain谁release
4.若是一个对象已经被释放了,这个对象就成为僵尸对象,再去使用这个对象就没有意义,默认不报错,须要开启僵尸对象检测
不能使用retain让僵尸对象起死回生
5.对象nil 类Nil NULL NSNull是一个对象
避免使用僵尸对象的方法是,对象释放之后,给对象赋值为nil
6.多个对象的内存管理
在set函数中先release实例对象,再retain传入的对象
//若是是同一个对象的话就不须要release和retain
if(_car!=car){
[_car release];
_car=[car retain];
}
在dealloc中,release实例对象
[_car release];
7.@property参数
1.原子性atomic nonatomic
2.读写readwrite readonly
3.内存管理assign retain copy
替换get方法名称setter=isVip,get方法名称getter=isVip
8.@class的使用
使用import引入头文件时,若是头文件的内容发生了变化,此时全部引用这个头文件的类都须要从新编译
使用@class 类名;代替import
告诉编译器xxx是一个类,不须要从新编译
可是使用时会有提示错误,解决办法,在.m文件中再import一次
@class的能够解决循环引入问题,A类和B类互相import,使用class不会报错
9.循环retain会致使两个对象都会内存泄露
防止方法:1)让某个对象多释放一次(注意顺序)
2)推荐方法:一端使用assign,另外一端使用retain
10.NSString对象
11.@autoRelease
若是一个方法须要放回一个新建的对象,该对象什么时候释放?
方法内部不会释放,由于这样作会将对象当即释放而返回一个空对象,调用者也不会主动释放该对象
这个时候就发生了内存泄露
1)@autoreleasepool {}建立自动释放池
2)[对象 autorelease];//加入自动释放池,发送消息,释放池结束的时候调用对象的release
autorelease的嵌套:
1)自动释放池的栈结构和内存的栈是不同的
2)对象存在栈顶的自动释放池中
12.id和instancetype的区别
instancetype能够智能帮咱们判断赋值的指针变量的类型和方法的返回值类型是否一致
13.autorelease的使用场景
如父类是Person在父类的person方法中使用autorelease,Student继承Person类
//
// Person.m // OC03 //
// Created by fanyafang on 15/11/7. // Copyright © 2015年 itcast. All rights reserved. //
#import "Person.h"
@implementation Person +(instancetype)person{ return [[[self alloc]init]autorelease]; } -(void)dealloc{ NSLog(@"Person释放了!"); } @end
在main方法中,建立自动释放池
#import <Foundation/Foundation.h>
#import "Student.h"
int main(int argc, const char * argv[]) { @autoreleasepool { //Person *p=[Person person];
Student *student = [Student person]; } return 0; }
14.重写初始化方法
//
// Student.h // OC03 //
// Created by fanyafang on 15/11/7. // Copyright © 2015年 itcast. All rights reserved. //
#import <Foundation/Foundation.h>
@interface Student : NSObject @property(nonatomic,assign) int age; -(instancetype)initWithAge:(int)age; +(instancetype)StudentWithAge:(int)age; @end
//
// Student.m // OC03 //
// Created by fanyafang on 15/11/7. // Copyright © 2015年 itcast. All rights reserved. //
#import "Student.h"
@implementation Student -(void)dealloc{ NSLog(@"释放了"); } -(instancetype)initWithAge:(int)age{ if(self=[super init]){ _age=age; } return self; } +(instancetype)StudentWithAge:(int)age{ return [[[self alloc]initWithAge:age]autorelease]; } @end
//
// main.m // 重写初始化方法 //
// Created by fanyafang on 15/11/7. // Copyright © 2015年 itcast. All rights reserved. //
#import <Foundation/Foundation.h>
#import "Student.h"
int main(int argc, const char * argv[]) { @autoreleasepool { /* Student *stu=[[Student alloc]initWithAge:10]; NSLog(@"stu age%d",[stu age]); [stu release]; */ Student *stu=[Student StudentWithAge:20]; NSLog(@"stu age%d",[stu age]); } return 0; }