一、内存管理



    1. 为什么要进行内存管理



      移动设备的内存极其有限,所以每个APP所占的内存也是有限制的,当app所占用的内存较多是,系统就会发出内存警告,每个app可以用的内存是被限制的,如果内存超过20M,系统就会对该APP发出Memeory Warning消息。收到此消息需要回收一些不需要继续使用的内存空间。





    2. OC内存管理范围



      管理范围:管理任何继承NSObject的对象,对其它类型基本无效。对象类型是程序运行过程中动态分配的,存储在堆区的内存管理主要是对堆区中的对象的内存管理。



OC对象存放于堆里面, 非OC对象一般放在栈里面(栈内存会被系统自动回收)。





   3. 对象所有权:任何对象可以拥有一个或多个所有者。只要对象拥有一个所有者,它就会继续存在。



       Cocoa所有权策略:任何自己创建的对象都归自己所有,可以使用名字以“alloc” 或 “new”开头或名字中包含“copy” 的方法创建对象,可以使用retain来获取一个对象的所有权。





引用计数器



       1)每个OC对象都有自己的引用计数器,是一个整数(8字节)表示对象引用的次数,即现在有多少东西在使用这个对象。对象刚被创建是,默认计数器值为1,当计数器的值为0时,则对象销毁。



      2)作用:引用计数器是判断对象要不要回收的依据(存在一种例外:对象值为nil时,引用计数器为0,但不回收空间),就是计数器是否为0。



      3)操作:给对象发消息,进行相应的计数器操作



        retain:使计数器+1,该方法返回对象本身。



        release:使计数器-1



        retainCount:获取对象当前引用计数器的值 %ld %tu(无符号长整型)



      4)对象销毁:当一个对象的引用计数器为0是,那么它就会被销毁,其占用的内存也就会被系统回收。



             当对象销毁时,系统就自动会给对象发送一条dealloc消息,一般会重写dealloc方法,在这里释放相关的资源。



            一旦重写了dealloc方法,就必须调用[super dealloc] ,并且放在代码块的最后调用



           一旦对象被回收了,那么它的存储空间就不再可用,强制使用会导致程序崩溃(野指针错误)





    5. OC内存管理分类:



         MRC 手动管理  ,ARC 自动引用计数,garbage collection(垃圾回收,iOS不支持)





    6. 内存管理的原则:



      1)原则:



             只要还有人使用某个对象,那么这个对象就应该被回收



             只要你想使用这个对象,那么就应该让这个对象的retain引用计数器+1



             当你不想使用这个对象时,那就就应该让这个对象release(引用计数器-1)



             注意:谁创建谁release,谁retain谁release





    7.内存管理研究的内容:



      1)野指针:定义指针没有进行初始化,指向的内存空间被释放



      2)内存泄漏:Person *p = [Person new];  栈区空间p释放了,但是堆区[Person new]没有被释放,那么堆区空间就被泄漏了



      3)僵尸对象就是:对象的空间已经释放掉了,Xcode默认是不检测僵尸对象。





   8. nil是一个对象的值



       NULL是一个通用指针



       NSNul 是一个对象,他不能使用nil的场合





   9. 单个对象内存管理



      1)泄漏问题:



            创建完成后,使用后没有使用release



            没有遵守内存管理原则



            不当使用nil



      2)避免使用僵尸对象的方法:将对象赋值nil





    10. 多个对象内存管理 



      set方法内存管理



       原则:如果在一个类中,有其它类的对象(关联关系),set方法中书写的时候,要判断是否是同一个对象,如果不是release掉旧值,retain新值。





二、@property



    1. get,set方法实现办法:



       1)@property + 手动实现



       2)@property int age + @synthesize age 



       3)@property int age  +@synthesize age = _age;



       4)增强@property 生成get 和set :@property int age 





    2. 参数 格式:@property (参数1 ,参数2) 数据类型 方法名



        



     3. 循环retain解决办法


        1)让某个对象先释放,另外一个对象多释放一次


        2)推荐方法:一端使用assign  一端使用retain



三、@class


    1. #import 作用:把要引用的头文件的内容,拷贝到#import处,如果引用的是#import “Person.h” 那么如果Person.h文件内容发生变化了,此时所有引用该头文件的类,需要重新编译。


    2. @class 作用:可以简单的引用一个类(告诉编译器这是一个类,不会包含其内容)


格式:@class 类名


         好处:引用头文件内容发生改变,而不需要重新编译


    4. 注意:


       1).h 使用@class xx;   .m 中使用#import "xx.h"


       2)假如A类中#import “B.h” ,B类中#import "A.h" 形成循环引用导致错误。@class可以解决循环引用问题



四、自动释放池


    1. 特殊栈结构


    2. 特点:对象可以加入自动释放池中,自动释放池结束时,会给池中的每一个对象发送一条release消息


@autoreleasepool {           }    //创建自动释放池


                    [对象 autorelease]           //将对象加入自动释放池中


不用再关心对象释 放的时间


                    不用再关心什么时候调用release


    5.  autorelease的使用注意


             占用内存较大的对象不要随便使用autorelease


             占用内存较小的对象使用autorelease,没有太大影响