• ios内存管理


    内存管理准则:

    (一)原则

    只要有人还在使用某对象,那么这个对象就不会被回收:只要你想使用这个对象,那么就应该让这个对象的引用计数+1,当你不想使用这个对象,就让对象的引用计数减一;

    (二)谁创建,谁release

    (1)如果你通过alloc,new,copy来创建一个对象,那么你就必须调用release或者autorelease方法

    (2)不是你创建的你就不用去负责了。

    (三)谁retain,谁release

    只要你调用了retain,无论这个对象是如何生成的,你都要调用release

    (四)总结

    有始有终,有加就有减。曾经让某个对象计数器加1,就该让其在最后-1.

    1.  

      alloc      对象分配后引用计数为1
        retain    对象的引用计数+1
        copy      copy 一个对象变成新的对象(新内存地址) 引用计数为1 原来对象计数不变
       
        release            对象引用计数-1 如果为0释放内存
        autorelease      对象引用计数-1 如果为0不马上释放,最近一个个pool时释放    
    NSLog(@"sMessage retainCount:%u",[sMessage retainCount]);
    [sMessage retain]; //2
    NSLog(@"sMessage retainCount:%u",[sMessage retainCount]);
    NSLog(@"sMessage retainCount:%u",[sMessage retainCount]);
    NSLog(@"sMessage retainCount:%u",[sMessage retainCount]);
        内存管理的原则就是最终的引用计数要平衡,
       如果最后引用计数大于0  则会内存泄露
       如果引用 计数等于0还对该对象进行操作,则会出现内存访问失败,crash    所以尽量设置为nil
       
       这两个问题都很严重,所以请一定注意内存释放和不用过后设置为nil
    2.
       每个工程都有一个 main.m 文件: 内容如下:
       int main(int argc, char *argv[]) {
       
        NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
        int retVal = UIApplicationMain(argc, argv, nil, nil);
        [pool release];
        return retVal;
    }
       很明显C语言的main 函数: 
      NSAutoreleasePool 是用来做autorelease 变量释放的,前面说了, autorelease不会马上释放,当他到了最近的pool release 时会检查reatin count 是不是为0, 为0就释放。 
    当我们在一段代码时加入了大量的autorelease变量时,我们应该为这段代码加上
    Autoreleasepool,其它时候不用
    在返回一个对象时常常要返回一个autorelease 对象,因为objectC 对象都是动态内存,没有
    栈的概念,所以不能像C/C++一样返回一个对象到栈,只能用autorelease对象。
    3.
        实际情况并非上面那么简单,你可能需要在一个函数里调用另一个函数分配的变量这时候
    有两个选择:  类成员变量和使用属性
       @interface TestMem: NSObject {
                TestObject   *m_testObject ;            // 成员变量
                TestObject   *testObject;                 //成员变量
        }
     成员变量与上面的内存管理是一致的,只是在不同的函数里要保持引用计数加减的平衡
    所以要你要每次分配的时候检查是否上次已经分配了。是否还能调用 
    什么时候用属性?
      1. 把成员做为public.
      2. outlet 一般声明为属性( 这个内存于系统控制,但我们还是应该做一样操作,后面会讲)
      3. 如果很多函数都需要改变这个对象 ,或这个函数会触发很多次,建议使用属性。我们看看属性函数展开后是什么样子:

    // assign
    -(void)setTestObject :(id)newValue{
        testObject= newValue;
    }
    // retain
    -(void)setTestObject  :(id)newValue{
        if (testObject!= newValue) {
            [testObject release];
            testObject= [newValue retain];
        } 
    }
    // copy
    -(void)setTestObject :(id)newValue{
        if (testObject != newValue) {
            [testObject release];
            testObject = [newValue copy];
        }
    }

  • 相关阅读:
    logback 常用配置详解(二) <appender>
    logback 配置详解(一)
    logstash报错如下:Validation Failed: 1: this action would add [2] total shards, but this cluster currently has [999]/[1000] maximum shards open
    从字节码角度分析Byte类型变量b++和++b
    接口和抽象类有什么区别?你选择使用接口和抽象类的依据是什么?
    计算1至n中数字X出现的次数
    转:轻松搞定面试中的红黑树问题
    转:40个Java集合面试问题和答案
    自定义Adapter为什么会重复多轮调用getView?——原来是ListView.onMeasure在作祟
    何时调用getView?——从源码的角度给出解答
  • 原文地址:https://www.cnblogs.com/fanxinguu/p/4373060.html
Copyright © 2020-2023  润新知