zoukankan      html  css  js  c++  java
  • 黑马IOS学习总结1--内存管理

    1、基本理论

    alloc new (mutable)copy 这三者会使计数器+1

    retain 返回其调用的对象本身

    示例:

    Person * p = [[Person alloc] init];    // retainCount 为1 ,p是在栈内存中,其内保存着指向堆内存中开创出来的Person对象地址的值。

    [p retain];  // 返回p本身,即可以写成 p = [p retain]  此时retainCount 为2 

    [p release]; // 计数器减1 retainCount 为1

    [p release]; // 计数器再减1 retainCount 为0 ,将自动调用person对象的 dealloc方法,释放内存。注意,此时,p 中仍然保存着person对象的地址值,但此时,联系已经断开了,堆内存中的person对象已经消除了,称为僵尸对象!p此时也称为野指针!

    p.age = 5; // 注意,此处等于调用僵尸对象赋值,可能会不报错。在Xcode中开启内存管理开关(僵尸对象检查机制),就会报错。打开方法:Edit schema --> Diagnostics -->Objective-c Enable Zombie Objects 上打钩

    [p release]; // 此时会报错。野指针指向的僵尸对象没法release;

    p = nil; // 将 p 这个野指针清空,此时称为 空指针

    [p release]; // 此处无错,空指针指向空对象可以release

    2、SET方法内存管理

    情况一:Person类中有一个属性car

    -(void) setCar:(Car *) car{

      _car = car;   // line 1

    }

    这样做是不妥的,主方法中调用一下说明这个不妥:

    Person * p = [[Person alloc]init];

    Car * c = [[Car alloc]init];  

    p.car = c;  // 调用上面set方法中的line 1 ,因无alloc copy new ,故 虽然 _car 使用并指向了 Car对象,但对Car对象的retainCount并无影响!

    [c release]; // Car对象retainCount 为 0 ,Car 对象消失

    ------此处,Person类对象还没消失,但其内的_car属性已无意义,因其所指的对象已经消失--------

    [p release]

    情况二:为改进情况一,修改set方法如下

    -(void) setCar:(Car *) car{

      _car = [car retain];   // line 2

    }

    -(void)dealloc{

       [_car release];  // 覆写dealloc方法,既然_car retain了一下Car对象,那么Person对象覆灭时候,作为其内属性的_car也应该release掉这次引用,这也是符合黄金法则的。

       [super dealloc];

    }

    其意思是,既然_car要使用Car对象,就应该对Car对象做一次引用保留,增加一次retainCount,说明_car在这个属性在使用着Car对象。

    但这样仍然是不完善的,主文件中调用一下说明这个不完善:

    Person * p = [[Person alloc]init];

    Car * c1 = [[Car alloc]init];  

    p.car = c1;  // c1的Car对象 引用计数为 2

    Car * c2 = [[Car alloc]init];  

    p.car = c2;  // c2的Car对象 引用计数为 2。同时,_car 不再指向 c1的Car对象!

    [c2 release]; // c2 retainCount 1

    [c1 release]; // c1 retainCount 1

    [p release];  // p覆灭,同时c2 retainCount 0; c1 retainCount 1,造成内存泄露

    情况三:继续改进情况二

    -(void) setCar:(Car *) car{

        if(_car != car){

        [_car release];   // 如果_car有旧值,那么这一步会使其释放所保留其指向对象的引用;如果没有旧值,等效于 [nil release] 也无不可

        _car = [car retain];   

        }

    }

    3、@property的参数释义

    1)有关set方法内存管理的

    retain 即上面情况三,release旧值,retain新值。适用于OC对象

    assign 即上面情况一,直接赋值,适用于非OC对象的基础类型(int,long,float等)   注意,默认是assign的。如果用到此项,即便默认,也要显式的写上!这是好习惯!

    copy release旧值,copy新值。

    2)是否要生成set方法

    readwrite 同时生成setter和getter的声明和实现

    readonly 只生成getter的声明和实现

    3)多线程管理 

    nonatomic 非多线程 性能高

    atomic 多线程  性能低 注意,默认是atomic的

    示例:

    @property(nonatomic,retain) NSString * name;

    @property(nonatomic,assign) int age;

    4、循环引用问题

    即:A类中有一个属性是B对象,B类中有一个属性是A对象。这种情况在使用过程中,是会报错的。解决方法如下:

    在一个类中用assign声明属性,另一个类中用retain声明属性即可

    额外说明:在.h文件中,用 @class 方式声明一个欲使用的类,在.m文件中再用#import引用类 (如有用到该类方法需导入此类时)

    5、autorelease

    A 使用了autorelease,就不必再顾虑对象在何处release了,对象会被扔到自动释放池里,工作完了会自动release池子里的对象。autorelease返回对象本身。

    注意:

    1)使用了autorelease,对象的引用计数并不会变化。

    2)占用内存较大的对象,不要随便使用autorelease,因为他会一直占用着内存,等待自动释放池销毁。反之,占用内存较小的对象,使用autorelease则没有多大影响。

    3)autorelease错误写法1:

    @autorelease{

      Person * p = [[[Person alloc] init] autorelease];  // 计数器为 1

         [p release]; // 计数器为0 此时p为野指针

     } // 自动释放池在此行销毁,会再次release一次其内的对象,也即再一次[p release],而此时p是野指针了,所以会报错

    错误写法2:

    @autorelease{

      Person * p =[[[[Person alloc] init] autorelease]autorelease];  

     }// 连续多次调用autorelease等效于自动释放池一销毁,会多次调用release,会引发野指针调用错误。

     B autorelease实用技巧

    若每次创建对象,都如此这般 Person * p = [[[Person alloc] init] autorelease]; 会显得很繁琐,尤其是多次创建对象。此时,可以在类中建立一个静态方法,示例如下:

    +(id) person{  return [[[self alloc] init ] autorelease]; }

    这样,每次创建对象的时候,只要 Person * p = [Person person];即可。

    注意,这里用self而不是Person是有讲究的,原因是考虑到Person的子类情况。例如,GoodPerson 继承 Person类,如果此处不用self,而用Person,那么 GoodPerson *gp = [GoodPerson person];实际返回的还是Person对象,这样子类中的一些方法就无法使用了。

    6、ARC

    ARC的判断准则:只要没有强指针指向对象,就会释放对象。

    指针分两种:

    1)强指针,默认情况下,所有指针都是强指针 __strong

    2)  弱指针,__weak   使用示例:__weak Person * p = [[Person alloc] init];

    手动管理内存到ARC的等效转变

    @propery(nonatomic,retain)  -----> @property(nonatomic,strong) 适用于OC对象

    @propery(nonatomic,assign)  -----> @property(nonatomic,weak)  适用于OC对象

    @propery(nonatomic,assign)  -----> @property(nonatomic,assign)  适用于基本类型

    循环引用问题在ARC中的解决:一个属性用strong,另一个用weak即可。

  • 相关阅读:
    (转载)VS2010/MFC编程入门之四十六(MFC常用类:MFC异常处理)
    (转载)VS2010/MFC编程入门之四十五(MFC常用类:CFile文件操作类)
    (转载)VS2010/MFC编程入门之四十四(MFC常用类:定时器Timer)
    (转载)VS2010/MFC编程入门之四十三(MFC常用类:CTime类和CTimeSpan类)
    Android笔记之ImageView
    Activity的四种launchMode
    Eclipse使用技巧
    ubuntu下使用MyEclipse以及MyEclipse Tomcat
    Android笔记之Json数据解析
    【转】[Android_机制]_Http和Socket连接区别
  • 原文地址:https://www.cnblogs.com/appzhang/p/3588169.html
Copyright © 2011-2022 走看看