码迷,mamicode.com
首页 > 其他好文 > 详细

Objective-C 内存管理

时间:2015-07-28 00:34:07      阅读:96      评论:0      收藏:0      [点我收藏+]

标签:

概述

开发的过程中,很多程序员都不会注意管理对象或者变量的内存,导致系统或者应用运行一段时间,就很慢了,或者崩溃。下面我们一起聊聊编程过程中的内存是如何进行管理的。

内存管理包含那些方面?

有效的内存管理,通常包含两方面内容:

  内存分配:当程序创建对象时需要为对象分配内存。采用合理的设计,尽量的减少对象的创建,并减少对创建过程中的内存开销。

  内存回收:当程序不再需要对象时,系统必须及时回收这些对象所占用的内存,以便程序可以再次使用这些内存。

 

iOS 5 之前,iOS开发人员,需要话费精力去处理内存回收相关的问题。iOS 5 之后,引入了心的特性:自动引用技术(ARC)。通过 ARC ,程序员可以不需要关注内存回收这块内容,可以大大的提高开发的效率。

  Objective-C 内存回收机制有以下方式

  • 手动引用计数 MRC
  • 自动引用技术 ARC

手动引用计数

目前创建的项目默认都是ARC的,如何可以将项目改为 MRC 模式呢?

创建项目,打开项目的配置界面,选择 Target -> Buld Setting -> 搜索 automatic reference , 如图设置
技术分享

将自动引用计数设置为NO,就可以手动引用计数了。

 

  Objective-C 采用来一种被称为引用计数的计数来跟踪对象的状态:每个对象都有一个与之关联的整数,这个整数被称为引用计数器。正常情况下,当一段代码需要访问某个对象时,该对象的引用计数加1;当这段代码不在访问改对象时,改对象的引用计数减1,表示这段代码不在访问该对象。当对象的引用计数为0的时候,表示程序已经不在需要该对象,系统就会回收改对象所占用的内存。

  系统在销毁该对象之前,会自动调用改对象的 delloc 方法来执行一些回收操作。

  当对象呗销毁之后,此时该对象已经不再存在;如果有一个指针指向这个被销毁的对象,这个指针酒杯称为悬空指针,也称为野指针,僵尸指针,调用该指针指向对象的方法时,程序往往会出现未知的结果,甚至导致程序崩溃。

 

在手动引用计数中,改变对象的引用计数的方式如下:

  • 当程序调用方法名以 alloc、new、copy、mutableCopy 开头的方法来创建对象时,该对象的引用计数加1.
  • 当程序调用对象的 retain 方法时,该对象的引用计数加1.
  • 当程序调用对象的 release 方式时,该对象的引用计数减1.

NSObject 中提供了有关引用计数的方法:

  • retain: 引用计数+1
  • release:引用计数-1
  • autorelease:不改变该对象的引用计数器的值,只是将对象添加到自懂释放池中。
  • retainCount:返回该对象的引用计数的值。

看看测试代码:

 1 //
 2 //  Item.m
 3 //  MRC
 4 //
 5 //  Created by 万齐鹣 on 15/7/27.
 6 //  Copyright (c) 2015年 万齐鹣. All rights reserved.
 7 //
 8 
 9 #import "Item.h"
10 
11 @implementation Item
12 
13 - (instancetype)init
14 {
15     self = [super init];
16     if (self) {
17         NSLog(@"init方法中,引用计数为:%ld", self.retainCount);
18     }
19     return self;
20 }
21 
22 -(void)dealloc
23 {
24     NSLog(@"调用销毁的方法");
25     [super dealloc];
26 }
27 
28 @end
//
//  main.m
//  MRC
//
//  Created by 万齐鹣 on 15/7/27.
//  Copyright (c) 2015年 万齐鹣. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "Item.h"

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // insert code here...
        Item * item = [[Item alloc] init]; // 引用计数1
        NSLog(@"%ld", item.retainCount);
        [item retain]; // 引用计数2
        NSLog(@"%ld", item.retainCount);
        [item retain]; // 引用计数3
        NSLog(@"%ld", item.retainCount);
        [item release]; // 引用计数2
        NSLog(@"%ld", item.retainCount);
        [item retain]; // 引用计数3
        NSLog(@"%ld", item.retainCount);
        [item release]; // 引用计数2
        NSLog(@"%ld", item.retainCount);
        [item release]; // 引用计数1
        NSLog(@"%ld", item.retainCount);
        [item release]; // 引用计数0
    }
    return 0;
}

运行的结果:

技术分享

 

 

手工内存管理规则的总结

  • 如果需要保持一个对象不被销毁,可以使用 retain 。在使用完对象后,需要使用 release 进行释放。
  • 给对象发送 release 消息并不会销毁这个对象,只当这个对象的引用计数减至0时,对象才会被销毁。然后系统会发送 dealloc 消息给这个对象用语释放对象。
  • 对使用了 retain 或者 copy、mutableCopy、alloc 或 new 方法的任何对象,以及具有 retain 和 copy 特性的属性进行释放,需要覆盖 dealloc 方法,使得对象被释放的时候能够释放这些事例变量。
  • 在自动释放池被清空时也会为自动释放的对象做些事情。系统每次都会在自动释放池被释放时发送 release 消息给池中的每个对象。如果池中的对象引用计数降为0,系统会发送 dealloc 消息销毁这个对象。
  • 如果在方法中不再需要用到这个对象,但需要将其返回,可以给这个对象发送 autolease 消息用意标记这个对象延迟释放。autolease 消息并不会影响到对象的引用计数。
  • 当应用终止时,内存中的所有对象都会被释放,不论它们释放在制动释放池中。
  • 当开发应用程序时,随着应用程序的运行,自动释放池会被创建和清空。在这种情况下,如果要时自动释放池被清空后自动释放的对象还能够存在,对象需要使用 retain 方法,只要这些对象的引用计数大于发送 autorelease 消息的数据,就能搞在池清理后生存下来。 

Objective-C 内存管理

标签:

原文地址:http://www.cnblogs.com/qijianwan/p/4681480.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!