zoukankan      html  css  js  c++  java
  • [学习笔记—Objective-C]《Objective-C-基础教程 第2版》第九章 内存管理

    内存管理:

    • 确保在须要的时候分配内存,在程序运行结束时释放占用的内存
    • 假设仅仅分配内存而不释放内存,则会发生内存泄漏(leak memory),程序的内存占用量不断添加。终于会被耗尽并导致程序崩溃。
    • 不要使用不论什么刚释放的内存,否则可能误用陈旧的数据。假设内存已经载入了其它数据,将会破坏这些新数据。

    9.1 对象生命周期

    对象的生命周期:

    1. 诞生:通过alloc或new方法实现
    2. 生存:接受消息并运行操作
    3. 交友:通过复合以及向方法传递函数
    4. 死去:被释放掉

    9.11 引用计数

    关于引用计数的操作:

    • 添加对象的保留计数器的值:发送retain 。方法:-(id) retain //返回值为id类型
    [[Car retain] setTire: tire atIndex:2];//car对象保留计数器的值+1并运行setTire的操作
    
    • 降低对象的保留计数器的值:发送release。方法:(oneway void)release;
    • 获得保留计数器当前的值:retainCount。方法:-(NSUInteger) retainCount;//格式化方法:%ld
    • 对象的保留计数器归0时,系统会自己主动向对象发送dealloc消息。
    • 能够在自己的对象中重写dealloc方法,这样能够释放掉已经分配的全部相关资源,不能直接调用dealloc方法。

    9.12 对象全部权

    • 某个实体拥有一个对象时,该实体就要负责将其拥有的对象进行清理
      • 假设一个对象内有指向其它对象的实例变量,则称该对象拥有这些对象
      • 假设一个函数创建了一个对象。则称该函数拥有这个对象
    main(){
    Car *car = [Car new];
    Engine *engine = [Engine new];//engine拥有engine对象
    
    [car setEngine: engine];//car拥有engine对象
    }

    注意:main()和Car类都拥有engine对象,怎样释放?

    • 让Car类在setEngie方法中保留engine对象。main()负责释放engine对象,Car类完毕任务时再释放engine对象

    9.13 訪问方法中的保留和释放

    -(void)setEngine: (Engine *)newEngine
    {
        [newEngine retain];    //先保留新的对象
        [engine release];      //释放旧的对象
        engine = newEngine;
    

    9.14 自己主动释放

    -(NSString *) description
    {
        NSString *description = [[NSString alloc] initWithFormat:@"I am %d years old", 4];
        return (destription);
    }
    
    main{
        NSString *desc = [someObject description];
        NSLog(@"@",desc);
        [desc release];
    }
    

    注意:在description方法中创建的字符串对象怎样释放?

    9.15 全部对象放入池中

    -(id)autorelease;//返回接受这条消息的对象
    • 当给一个对象发送autorelease消息时,是将对象加入到了自己主动释放池中,当自己主动释放池被销毁时,会像该池中的全部对象发送release消息。
    -(NSString *) description
    {
        NSString *description = [[NSString alloc] initWithFormat:@"I am %d years old", 4];
        return ([destription autorelease]);//对象暂时放入池中,等调用NSLog代码结束后。自己主动释放池会被自己主动销毁
    }
    
    main(){
        NSLog(@"@",[someObject description]);
    }
    

    9.16 自己主动释放池销毁时间 略

    9.17 自己主动释放池的工作流程

    
    int main ()
    {
        NSAutoreleasePool *pool;
        pool = [[NSAutoreleasePool alloc] init];
    
        RetainTracker *tracker;
        tracker = [RetainTracker new]; // count: 1
    
        [tracker retain]; // count: 2
        [tracker autorelease]; // count: still 2,自己主动释放池有一个引用指向了该对象,当自己主动释放池被销毁时。将给tracker对象发送一条release消息。保留计数器的值仍然大于0,仍处于活动状态。

    [tracker release]; // count: 1 NSLog (@"releasing pool"); [pool release]; //dealloc方法调用 return (0); }

    9.2 Cocoa的内存管理规则

    • 使用new。alloc,或copy方法创建对象时。该对象的保留计数器为1。

    • 假设通过其它对象获得一个对象时,假设该对象的保留计数器值为1,并且一景被设置为自己主动释放,那么不须要运行不论什么操作确保该对象得到清理。
    • 假设打算一段时间拥有对象,则须要保留它并确保在操作完毕时释放它。

    • 假设保留了某个对象,就须要终于释放或自己主动释放该对象。

      必须保持retain方法和release方法的使用次数相等。

    注意:当拥有一个对象的时候。须要弄清楚:怎样获得对象的?打算拥有多长时间?

    9.21 暂时对象

    并未打算长期拥有对象的情况下:暂时对象

    • 假设是用new,alloc。copy方法获得的这个对象。就须要安排好该对象的内存释放
    • new。alloc,copy以外的方法获得对象。则能够假设该对象被返回时保留计数器的值是1并且被设置为自己主动释放。

    9.22 拥有对象

    在多段代码中一直拥有某个对象。将她们加入到诸如NSArray或NSDictionary集合中

    • 假设使用了new,alloc。copy方法获得了一个对象。仅仅须要在拥有该对象的dealloc方法中释放它就可以。

    -(void)dostuff
    {
        flonkArray = [NSMutableArray new]; //count:1
    }
    
    -(void) dealloc
    {
        [flonkArray release]; //count:0
        [super dealloc];
    }
    
    • 假设使用new。alloc。copy以外的方法获得了一个对象。须要保留该对象,由于在事件循环结束后或自己主动释放池被销毁时,该对象会收到一条release消息。

    -(void)dostuff
    {
        flonkArray = [NSMutableArray arrayWithCapacity:17]; //count:1,autoreleased
    
    }
    
    -(void) dealloc
    {
        [flonkArray release]; //count:0 
        [super dealloc];
    }
    

    注意:自己主动释放池被清理的时间是全然确定的:在代码中你自己手动销毁;使用AppKit时在事件循环结束时结束。

    9.23 垃圾回收:自己主动内存管理机制

    垃圾回收器定期检查变量和对象并且跟踪它们的指针,发现没有不论什么变量指向某个对象时,就将该对象视为应该丢弃的垃圾。

    假设实例变量指向某个对象,一定要将该实例赋值为nil。取消对该对象的引用并告知垃圾回收器该对象能够清理了。

    注意:

    • 垃圾回收仅仅支持OSX开发,无法用在ios应用程序上。苹果公司不建议在自己的代码中使用autorelease方法,也不要使用会返回自己主动释放对象的一些便利的方法:stringWith:
    • 垃圾回收器在运行时工作。通过返回的代码定期检查对象

    9.24 自己主动引用计数

    • 自己主动引用计数(automatic refrence counting。ARC):系统追踪对象并决定哪一个仍会使用,哪一个不会再用到。

    • ARC在编译时进行工作的,在代码中插入了retain和release语句。

    • 有效范围:可保留的对象指针

      • 代码块指针
      • Objective-C指针
      • 通过attribute((NSObject))类型定义的指针
    • 使用ARC满足的条件:

      • 能够确定哪些对象须要内存管理
      • 能够表面怎样管理对象
      • 有可行的办法传递对象的全部权
    • A引用了B。B的引用计数器+1,强指针。被引用的+1

    • A释放了B,B的引用计数器-1;被释放的-1

    • 归零弱引用:zeroing weak reference 若引用的对象被释放的情况下,若引用会被设置为0

    声明归零弱引用:

    • _weak NSString *mystring
    • @property (weak) NSString *myString

    注意:内存管理的关键字和特性是不能一起用的

    垃圾回收机制禁用的前提下才干使用ARC
    转换之前确保代码符合ARC的需求
    一旦转换成ARC版本号,就不能够再恢复了

    • 拥有者权限:为了让ARC便于工作,须要告诉编译器哪个对象时指针的拥有者。

      • (_bridge)传递指针但不会传递它的全部权
      cfstring = (_bridge CFStringRef)theString;
      //指针的全部权仍然由theString保留
      
      • (_bridge_retain):全部权转移到non-ROP上

        cfstring = (_bridge_retain CFStringRef)theString; 
        //cfstring拥有指针并且保留计数器+1
      • (_bridge_transfer):全部权交给ROP

        ARC拥有对象并能确保它会像其它ARC对象一样得到释放

    9.3 异常

    NSException类来表示异常

    • 抛出异常(提出异常):处理异常的行为,通知异常的行为
    • 捕捉异常:处理被抛出的异常的行为

    假设一个异常被抛出可是没有被捕捉到。程序会在异常断点处停止运动并通知有这个异常。

    9.31 与异常有关的关键字

    • @try:定义用来測试的代码块决定是否抛出异常
    • @catch:定义用来处理已抛出异常的代码块
    • @finally:不管是否有抛出异常都会运行代码块
    • @throw:抛出异常

    9.32 捕捉不同类型的异常

    • 多个@catch代码块。处理代码应该依照从详细到抽象的顺序排序

    9.33 抛出异常

    • 当程序检測到了异常。就必须向处理它的代码块报告这个异常
      • 使用@“throw异常名”
      • 向某个NSException对象发送raise消息
    NSException *theException = [NSException exceptionWithName: ];
    @throw theException; //抛出异常,能够用在其它对象上
    [theException rasie];//抛出异常,raise仅仅对NSException对象有效
    
  • 相关阅读:
    tomcat启动超时
    sqlserver存储过程及mybatis调用——待续
    linux各种顔色代表
    linux ngix安装
    vue 报错解决:TypeError: Cannot read property '_t' of undefined"
    给iview项目加一个i18n国际化翻译
    初探iview
    vue-eslint配置文件
    js中通过Object.prototype.toString方法----精确判断对象的类型
    判断是对象还是数组的方法
  • 原文地址:https://www.cnblogs.com/brucemengbm/p/7290533.html
Copyright © 2011-2022 走看看