Logo Image
Published on

ios内存原理(1)

Authors
  • Profile Image
    Name
    jamesitachi
Table of Contents

board1.jpg 在iOS的开发中我们接触到了ARC/MRC这些机制,为了更好的了解其中的原理,我们可以从官方的文档作为入口来看看这些名词背后更深入的意义.

在iOS的开发中我们接触到了ARC/MRC这些机制,为了更好的了解其中的原理,我们可以从官方的文档作为入口来看看这些名词背后更深入的意义.

01内存管理

基本内存管理规则内存管理模型基于对象所有权。任何对象都可以具有一个或多个所有者。只要一个对象至少具有一个所有者,它就会继续存在。如果对象没有所有者,则运行时系统会自动销毁它.

苹果给出了四条准则

  • 管理任何由你自己创建的对象
  • 通过retain来持有一个对象 (在对象方法/init方法中调用 )一般在下面两种情况
    • 当你想将一个对象存储为属性值时
    • 当你想防止一个对象被释放时
  • 当你不再需要这个对象时候 请释放
    Person *aPerson = [[Person alloc] init];
    // ...
    NSString *name = aPerson.fullName;
    // ...
    [aPerson release];

tips 1.在iOS中涉及到对象持有的是基于一套 NSObject protocol协议 以及一些标准的方法名来实现的,例如alloc,newObject,copy,mutableCopy来实现的

2.管理对象,我们从Apple给出的两个例子

当你担心你的对象alloc后,在return之前调用[object release]导致对象被释放 那么采用autorelease,该方法会在返回对象之后调用release方法

- (NSString *)fullName {
    NSString *string = [[[NSString alloc] initWithFormat:@"%@ %@",
                                          self.firstName, self.lastName] autorelease];
    return string;
}

下面这种方法是在调用者调用此方法之后 对象被销毁之前达到将对象传递给外面的效果

- (NSString *)fullName {
    NSString *string = [NSString stringWithFormat:@"%@ %@",
                                 self.firstName, self.lastName];
    return string;
}

我们也可以通过ClassName 或者 id 去完成我们的逻辑操作例如&object指向内存地址 ,所以我们不持有对象就无需去管理对象


02实用的内存管理方法

1.我们在开发过程中对于一个类的管理是很常见的,例如一个继承NSObject类 拥有属性值

@interface Counter : NSObject
@property (nonatomic, retain) NSNumber *count;
@end;

- (NSNumber *)count {
    return _count;
}

2.我们优先采用 访问器方法(即gettter)方法,即使它看起来繁琐,但是他可以将release retain 方法给避免掉,进而内存管理起来更方便 同理我们使用访问器去设置属性时,也可以采用官方推荐做法 去避免产生对象

//这种没有产生NSNumber对象
- (void)reset {
    NSNumber *zero = [NSNumber numberWithInteger:0];
    [self setCount:zero];
}

//下面这种就需要手动管理
- (void)reset {
    NSNumber *zero = [[NSNumber alloc] initWithInteger:0];
    [self setCount:zero];
    [zero release];
}

3.不要在initializer 和delloc中使用访问器方法 如果需要在init中调用 请操作如下 因为在init方法中 self初始化还未完成.

- init {
    self = [super init];
    if (self) {
        _count = [[NSNumber alloc] initWithInteger:0];
    }
    return self;
}

03 弱引用避免循环引用

retain是对一个对象的强引用,当一个对象的强引用被释放的条件是当前没有人再引用它.当A -> B且 B -> A时候 彼此被对方强引用,导致满足释放的条件,此时就会造成内存泄漏. 为了解决循环引用我们需要引入 如弱引用 weakReference 在cocoa中规定:parent客体对child保持强引用,但是child对parent应具有弱引用

  • data source (数据源)
  • outline view item (view)
  • observers(通知的观察者)
  • miscellaneous targets and delegates(目标和代理)

04避免对象被释放

1.从数组或者字典中移除的对象

//当对象被移除之后 heisenObject为空了
heisenObject = [array objectAtIndex:n];
[array removeObjectAtIndex:n];
heisenObject could now be invalid.

2.父对象被释放了

3.给一个已经释放的对象调用[object release],如1中的 [heisenobject release]之后

使用autoreleasepool

autoreleasepool自动释放池 是可以循环嵌套的

@autoreleasepool {
    //创建自动释放对象的代码。
}

@autoreleasepool {
    //创建自动释放对象的代码。
    @autoreleasepool {
    //创建自动释放对象的代码。
  }
}

有三种情况下会使用到自动释放池

  • 不基于UIkit开发的程序
  • 创建很多的临时对象循环
  • 生成第二个线程 (一旦线程看是执行 那么就必须创建自己的自动释放池块 否则就会出现内存泄漏的对象)