OC进阶(二)
1.autorelease注意及错误用法
#import <Foundation/Foundation.h> #import "Person.h" /** * autorelease的使用注意 */ void test(){ //1 自动释放池 Person *p = [Person new]; @autoreleasepool { //autorelease的使用注意: // 1)并不是所有的放到自动释放池中的代码,产生的对象就会自动释放 // 如果需要释放,必须加入到自动释放池 // Person *p = [[Person new] autorelease]; //我们只需要在自动释放池代码块中调用autorelease 就可以把对象 //加入到自动释放池 [p autorelease]; } //2) 如果对象调用了autorelease 但是,调用autorelease的时候,没有在任何一个自动释放池中,此时该对象也不会 被加入到自动释放池 // Person *p = [[Person new] autorelease]; } /** * 自动释放池的嵌套 */ void test2(){ Person *p = [[Person alloc] init]; [p retain]; //2 //autoreleasepool的嵌套 //自动释放池的栈结构(数据结构),和内存的栈区是不一样的 // 对象存在 位于栈顶位置的自动释放池中 @autoreleasepool { @autoreleasepool { @autoreleasepool { [p autorelease]; //20M for(int i=0;i<10000;i++){ Person *temp = [[Person new] autorelease]; } //1000行 }// [p release]; //1 [p autorelease]; }// } } int main(int argc, const char * argv[]) { Person *p = [[Person alloc] init]; //1 //autoreleasepool的嵌套 //自动释放池的栈结构(数据结构),和内存的栈区是不一样的 // 对象存在 位于栈顶位置的自动释放池中 @autoreleasepool { [p autorelease]; }// [p release]; 1---->0 [p release]; //错误的用法 return 0; }
2.autorelease的应用场景
+(instancetype)person{ //Person person ---> Person //Stduent person ----> Student //创建对象 return [[[self alloc] init] autorelease]; //返回的时对象的空间 //能够帮我们把对象给加入到自动释放池 }
//帮我们快速的创建对象,并且管理对象的内存(加入到自动释放池) // Person *p = [Person person]; // 1) 创建一个对象 p // 2) 用完之后,系统把对象释放掉 p
3.ARC机制
/* ARC机制 1) 判断是否是ARC机制 查看项目信息 不能使用retain release autorelease retainCount 在dealloc方法中不能使用 [super dealloc]; 2) 使用 正常创建对象,不用手动释放对象 */ #import <Foundation/Foundation.h> #import "Dog.h" int main(int argc, const char * argv[]) { @autoreleasepool { //ARC机制下对象的释放 Dog *jd = [Dog new]; [jd run]; } return 0; }
4.ARC单对象内存管理
#import <Foundation/Foundation.h> #import "Car.h" int main(int argc, const char * argv[]) { @autoreleasepool { //在ARC下对象释放的判断依据: 对象没有强指针指向 //对象会立即释放内存空间 // bigBen 强指针(指针默认的都是强指针) Car *bigBen = [Car new]; //定义另外一个强指针指向 //__strong 修饰符,修饰这个指针是一个强指针,也可以不写 //__weak 修饰的这个指针是若指针 // __strong Car *bmw = bigBen; __weak Car *bwm2 = bigBen; NSLog(@"bigBen = %@,bwm2 = %@",bigBen,bwm2); //bigBen的指向发生改变,对于Car对象来说没有强指针指向了,所以要释放对象 bigBen = nil; // // 要 1) bigBen 是强指针,重新指向其他内容了,对于对象来说没有强指针了 // 2) 弱指针 赋值为nil NSLog(@"bigBen = %@,bwm2 = %@",bigBen,bwm2); [bwm2 run]; //[nil run]; [bigBen run]; //[nil run]; NSLog(@"xxxxxx"); } return 0; }
5.ARC多对象内存管理
int main(int argc, const char * argv[]) { @autoreleasepool { // Dog *byd = [Dog new]; Person *p = [Person new]; p.dog = byd; // 1)在 @property (nonatomic,weak) Dog *dog; // byd = nil // Dog对象会立即释放 // 因为该对象没有强指针指向了 // 2)在 @property (nonatomic,strong) Dog *dog; // byd = nil // Dog对象不会被立即释放 // byd = nil; } return 0; }
6.ARC下循环引用问题
int main(int argc, const char * argv[]) { @autoreleasepool { //dog p 都是局部变量 //局部变量的生命周期: 从定义的位置开始,到它所在的代码块"}"结束 Dog *dog = [Dog new]; Person *p = [Person new]; //构成一个循环引用 p.dog = dog; //_dog weak类型 dog.owner = p; NSLog(@"xxxxx"); } return 0; }
7.分类
/* 分类: 一些方法的声明和实现 作用: 在不修改类的源代码的前提下,给类增加新的功能 使用步骤: //此处是声明一个类 @interface Person : NSObject @end //类的实现 @implementation Person @end 1) 声明一个分类 格式: @interface 待扩展的类名 (分类的名称) @end Person+base -->分类文件的命名规则 eat run 如: @interface Person (base) //吃 -(void)eat; //跑 -(void)run; @end 2) 实现这个分类 格式: @implementation 待扩展的类 (分类的名称) @end 如: Person+base 类别实现 @implementation Person (base) //吃 -(void)eat{ NSLog(@"人会吃东西"); } //跑 -(void)run{ NSLog(@"人会跑"); } @end 3) 使用分类中的方法 和使用类中原有的对象一样 Person *p = [Person new]; [p xxx]; playGame类别 --- 张三 playlol playdota study 类别 --- 李四 studyc studyios */
/* 分类的使用注意事项: 1) 在分类的声明中不能声明实例变量 不能定义实例变量 也不能使用 @property 2) 在分类的方法中,可以访问类中的实例变量 3) 在分类中存在和类同名的方法 优先访问的时 分类中 的方法 4) 当在多个类别中有同名的方法的时候,这时候,执行的最后编译的那个类别的同名方法 分类的 > 原类 最后编译的分类 > 其他的分类 */
#import "Person.h" @interface Person (playGame) //增加一个类别,类别名称 playGame 给Person增加新的方法 -(void)playLol; -(void)playDota; @end
#import "Person+playGame.h" @implementation Person (playGame) -(void)playLol{ NSLog(@"那人正在玩撸啊撸"); } -(void)playDota{ NSLog(@"那人正在玩刀塔"); } @end
8.类扩展
#import "Person.h" #import "Person_work.h" //扩展\延展\延展分类 //延展是一个特殊的分类 //特点: // 1) 可以在延展中 定义实例变量 // 2) 不能使用 @implementation 类名() 实现类别的方法 // 3) 作用,可以定义私有的变量和方法 @interface Person () { float _weight; } -(void)run; //run 相对私有的方法 @end @implementation Person -(void)run{ NSLog(@"延展的run方法 %.2f",_weight); } // Person_work.h 声明的,延展 -(void)work{ NSLog(@"work %d",_height); } -(void)test{ [self run]; [self work]; } @end