Objective-C内存管理基础
本文我们将介绍《Objective-C内存管理基础》,在iOS开发中,内存管理是开发者必须关心的东西,本文将简述一下Objective-C的内存管理机制和方法和一些特性。
对于我们.net开发人员来说,.net为我们提供了自动内存管理的机制,我们不需去关心内存的管理。但是iPhone开发中却是不能的。这篇文章将简述一下Objective-C的内存管理机制和方法和一些特性。
手动的进行内存管理
Cocoa和Objective-C的类都是NSObject的子类。NSObject中有几个方法进行内存管理。alloc方法为对象分配一片内存空间。dealloc方法用于释放对象的空间。但是在我们的代码中将永远都不会使用dealloc方法,因为运行时会为你调用此方法释放内存空间。而你需要做的只是引用计数,稍后介绍什么是引用计数。
除了alloc和dealloc,NSObject的还有retain和release方法两个方法用于引用计数。retain方法给retainCount变量加1,release方法给retainCount变量减1。当使用alloc为对象分配一片内存空间的时候,retainCount会为1。在这个对象的生命周期内,这个对象可能继续被其它变量引用。但有新的变量指向这个对象的时候,你应该调用retain方法,这样运行时才会知道有新的引用指向了这个变量,在这个对象生存期中拥有它的使用权。这个被Objective-C开发人员称之为“拥有”。例如:
- Foo * myFooOne = [[Foo alloc] init]; //retaincount 为1
- Foo * myFooTwo = myFooOne; //myFooTwo 指向了这个对象
- //retaincount 仍然为1
- [myFooTwo retain]; //调用retain方法,运行时才知道myFooTwo指向了该对象,retaincount 为2
上面的代码中,myFooTwo通过调用retain方法,取得了Foo对象的拥有权。在这个对象的生命周期中,会有很多变量来指向和引用它。指向这个对象的变量也可以通过release方法来解除这种拥有权。release方法将会告诉运行时,我已经使用完这个变量了,已经不需要它了,retainCount计数减1。
当对象的retainCount的计数大于或者等于1的时候,运行时会继续维持这个对象。当对象的retainCount为0的时候,运行时会释放这个对象,并回收它占得内存空间。
下图展示了一个Foo对象的生命周期。Foo对象首先在内存中分配一个内存空间,并且被myFooOne引用。在这个时候Foo对象的retaincount为1。
Foo * myFooOne = [[Foo alloc] init];

第二个引用变量指向Foo对象,这个引用变量接着调用retain方法,其实也是调用Foo对象的retain方法。Foo对象的retaincount变成2。
- Foo * myFooTwo = myFooOne;
- [myFooTwo retain];
接着当myFooOne引用不需要的时候,通过调用release方法,解除与Foo对象的拥有权,Foo对象的retaincount变成1。
- [myFooOne release];
但myFooTwo不在需要的时候,同样通过调用release方法,解除与Foo对象的拥有权,Foo对象的retaincount变成0。
内存泄露
我们经常会在一个方法中声明对象,看下面这个例子:
- -(void) myMethod {
- //incorrect method
- NSString * myString = [[NSString alloc] init]; //retainCount = 1
- Foo * myFoo = [[Foo alloc] initWithName:myString]; //retainCount = 1
- NSLog(@"Foo's Name:%@", [myFoo getName]);
- }
这上面这个方法中,我们为myString 和myFoo分配了内存空间。方法执行结束之后,两个变量超出了作用域的范围,所以不再有效。但是这个方法并没有releases这两个对象。所以运行时没有释放这两个变量占据的内存空间。除非你的应用程序结束,否则这两个变量占据的内存空间一直都是不可用的。我们把它称之为内存泄露。
为了防止内存泄露。无论什么时候,我们创建一个对象,或者创建一个对象的拷贝,我们都必须通过release方法释放。
- -(void) myMethod {
- NSString * myString = [[NSString alloc] init]; //retainCount=1
- Foo * myFoo = [[Foo alloc] initWithName:myString]; //retainCount=1
- NSLog("Foo's Name:%@", [myFoo getName]);
- [myFoo release]; //retainCount=0 so deallocate
- [myString release]; //retainCount=0 so deallocate
- }
弱引用
看下面的例子:
- -(void) myMethod {
- //an incorrect method
- Foo * myFooOne = [[Foo alloc] initWithName:@"James"]; //retainCount=1
- Foo * myFooTwo = myFooOne; //retainCount still 1
- [myFooOne release]; //retaincount=0 so deallocated
- NSLog("Name:%@", [myFooTwo printOutName]); //runtime error
- }
nyFooTwo指向了Foo对象,但是没有调用retain方法,就是一种弱引用,上面的代码会在运行时报错。因为myFooOne调用release方法。retaincount变成0,运行时,回收了对象的内存空间。然后myFooTwo调用printPutName自然就报错了,见下图说明。

总结:本文简单的介绍了一下手动的进行内存管理、内存泄露、弱引用等Objective-C的知识。
Objective-C内存管理基础的更多相关文章
- OC内存管理基础
OC 内存管理基础 一. retain和release基本使用 使用注意: 1.你想使用(占用)某个对象,就应该让对象的计数器+1(让对象做一次retain操作) 2.你不想再使用(占用)某个对象,就 ...
- Objective C内存管理之理解autorelease------面试题
Objective C内存管理之理解autorelease Autorelease实际上只是把对release的调用延迟了,对于每一个Autorelease,系统只是把该Object放入了当前的A ...
- .NET基础拾遗(1)类型语法基础和内存管理基础
Index : (1)类型语法.内存管理和垃圾回收基础 (2)面向对象的实现和异常的处理 (3)字符串.集合与流 (4)委托.事件.反射与特性 (5)多线程开发基础 (6)ADO.NET与数据库开发基 ...
- JVM内存管理基础
JVM 虚拟机架构(图片来源: 浅析Java虚拟机结构与机制) JVM 内存区域 JVM会将Java进程所管理的内存划分为若干不同的数据区域. 这些区域有各自的用途.创建/销毁时间: (图片来源: ...
- objective C 内存管理及属性方法具体解释
oc为每一个对象提供一个内部计数器.这个计数器跟踪对象的引用计数,当对象被创建或拷贝时.引用计数为1.每次保持对象时,调用retain接口.引用计数加1.假设不需要这个对象时调用release,引用计 ...
- .NET基础拾遗(1)类型语法基础和内存管理基础【转】
http://www.cnblogs.com/edisonchou/p/4787775.html Index : (1)类型语法.内存管理和垃圾回收基础 (2)面向对象的实现和异常的处理 (3)字符串 ...
- Objective C 内存管理[转]
1 配对原则 alloc – release new – release retain - release copy – release 2 new和alloc-init的区别 (1)区别只在于a ...
- Object-C内存管理基础
如果你通过手工alloc的方式分配内存实例化创建一个对象,之后你需要release这个对象,同理你也不能手工释放(release)一个能自动释放(autoreleased)的对象,因为这个样子会使你的 ...
- .NET基础拾遗(1)类型语法基础和内存管理基础2
二.内存管理和垃圾回收 2.1 .NET中栈和堆 每一个.NET应用程序最终都会运行在一个OS进程中,假设这个OS的传统的32位系统,那么每个.NET应用程序都可以拥有一个4GB的虚拟内存..NET会 ...
随机推荐
- SQL server 2008定期的备份数据库及删除job
在SQL Server中出于数据安全的考虑,所以需要定期的备份数据库.而备份数据库一般又是在凌晨时间基本没有数据库操作的时候进行,所以我们不可能要求管理员 每天守到晚上1点去备份数据库.要实现数据库的 ...
- 各种Map的区别,想在Map放入自定义顺序的键值对
今天做统计时需要对X轴的地区按照地区代码(areaCode)进行排序,由于在构建XMLData使用的map来进行数据统计的,所以在统计过程中就需要对map进行排序. 一.简单介绍Map 在讲解Map排 ...
- python pandas groupby
转自 : https://blog.csdn.net/Leonis_v/article/details/51832916 pandas提供了一个灵活高效的groupby功能,它使你能以一种自然的方式对 ...
- python split() 用法
字符串的split用法 说明:Python中没有字符类型的说法,只有字符串,这里所说的字符就是只包含一个字符的字符串!!!这里这样写的原因只是为了方便理解,仅此而已. 由于敢接触Python,所以不保 ...
- ACdream 1084 寒假安排(阶乘素因子分解)
题目链接:传送门 分析: 求A(n,m)转化成k进制以后末尾0的个数.对k素因子分解,第i个因子为fac[i], 第i个因子的指数为num[i],然后再对n的对A(n,m)进行素因子分解,设cou ...
- 【Android】15.0 第15章 广播和通知—本章示例主界面
分类:C#.Android.VS2015: 创建日期:2016-02-28 一.简介 广播(Broadcast):其功能类似于收音机的广播,你只要调到那个台(只要在接收的类中注册了要接收的广播),就能 ...
- rabbitMQ之安装和配置(一)
前言 erlang是一门面向并发的编程语言,流行的消息队列rabbitMQ是基于erlang环境运行的: 下载安装erlang语言环境 源码安装 # 从官网下载,在任何目录下,使用root权限 wge ...
- location ^~ /images/
} location ^~ /images/ { root /static/; } #当匹配到/images/ 开头的uri 会把网站定位到/static/下,并且不在向下继续匹配!!! 注意: ^~ ...
- Struts2初学 Struts.xml详解二
A.使用继承实现设置全局视图 package节点中还可以设置全局的视图,如: <global-results> <result name="e ...
- 如何在Windows下面运行hadoop的MapReduce程序
在Windows下面运行hadoop的MapReduce程序的方法: 1.下载hadoop的安装包,这里使用的是"hadoop-2.6.4.tar.gz": 2.将安装包直接解压到 ...
