内存管理

      1. 内存管理是程序设计中常见的资源管理的一部分。使用java和脚本语言则不需要考虑此类问题,这些语言的内存管理是自动进行的。如果我们只分配而不释放内存,会发生内存泄漏。程序的内存占用量不断地增加,最终会被耗尽并导致程序崩溃。同样需要注意的是,不要使用任何刚释放的内存,否则可能会误用陈旧的数据,从而引发各种各样的错误,而且如果该内存已经加载了其他数据,将会破坏这些新的数据。

     2. 对象的生命周期包括诞生(通过alloc或new方法实现)、生存(接收消息并执行操作)、交友(通过复合以及向方法传递参数)以及最终死去(被释放掉)。

3. 引用计数

    Cocoa采用了一种叫做引用计数的技术,有时候也叫做保留技术。每个对象都有一个与之相关的整数,被称作它的引用计数器或者保留计数器。

     当使用alloc,new方法或者通过copy消息(接收到消息的对象会创建一个自身的副本)创建一个对象时,对象的保留计数器会设置为1.要增加对象的保留计数器的值,可以给对象发送一条retain消息。要减少的话,可以给对象发送一条release消息。

     当一个对象因其保留计数器归0而即将销毁时,Objective-C会自动向对象发送一条dealloc消息。你可以在自己的对象中重写 -dealloc方法,这样就能释放掉已经分配的全部资源。一定不要直接调用dealloc方法,Objective-C会在需要销毁对象时自动调用它。

4. 自动引用计数

     垃圾回收机制只用于电脑,不可以用于手机,因为垃圾回收机制会对移动设备的可用性产生非常不利的影响,因为移动设备比电脑更私人化,资源更少。用户可不想在玩游戏或者打电话的时候因为系统突然进行内存清理而卡住。

   苹果公司的解决方案被称为自动引用计数(ARC)。顾名思义,ARC会最终你的对象并决定哪一个仍会使用而哪一个不会再用到。如果你启用了ARC,编译器会帮你插入retain和release语句,无需你自己动手。

说明: ARC只对可保留的对象指针(ROPS)有效。可保留的对象指针主要有以下三种:

       (1)代码块指针

       (2) Objective-C对象指针

       (3)通过 _attribute_((NSObject))类型定义的指针

        所有其他的指针类型,比如char* 和 CF对象(例如CFStringRef)都不支持ARC特性。

    如果你想在代码中使用ARC,必须满足以下三个条件:

   1. 能够确定哪些对象需要进行内存管理

   2. 能够表明如何去管理对象

   3. 有可行的办法传递对象的所有权

第一个条件是对象的最上层知道如何去管理它的子对象。比方说你有一个通过malloc:方法创建的字符串数组:

NSString *myString;

myString = malloc(10 * sizeof(NSString *));

这段代码创建了一个指向10个字符串的C型数组。因为C型数组不是可保留的对象,所以你无法在这个结构体中使用ARC特性。

第二个条件是你必须能够对某个对象的保留计数器的值进行加1或者减1的操作。也就是说所有的NSObject类的子类都能进行内存管理。这包括了你大部分需要管理的对象。

第三个条件是在传递对象的时候,你的程序需要能够在调用者和接收者之间传递所有权。

1. 有时候Weak会好一些

        当用指针指向某个对象时,你可以管理它的内存(通过retain和release),也可以不管理。如果你管理了,你就有了这个对象的强引用(strong reference)。如果你没有管理,那么你就拥有的则是弱引用(weak reference)。比方说,对属性使用assign特性,你便创建了一个弱引用。

       为什么会有弱引用?因为它们有助于处理保留循环。

     举例:假设你拥有3个对象的时候,假设对象A通过强指针指向对象B,而对象C通过弱引用指向对象B。如果对象A释放了对象B,那么对象C仍将拥有指向对象B的弱引用,但这个引用已经失效了,直接使用它会导致问题,因为指向的地方已经没有有效值了。

     解决的方法就是让对象自己去清空弱引用的对象。这种特殊的弱引用被称为归零弱引用(zeroing weak reference),因为在指向的对象释放之后,这些弱引用就会被设置为零(即nil),就可以像平常指向nil值的指针一样被处理。

   如果要使用归零弱引用,必须明确的声明它们。有两种方式可以声明归零弱引用:声明变量时使用_weak关键字或者对属性使用weak特性。

 _weak NSString *myString;

@property(weak) NSString *myString;

        如果你想在不支持弱引用的旧系统上使用ARC怎么办呢?苹果公司提供了_unsafe_unretained关键字和unsafe_unretained特性,它们会告诉ARC这个特殊的引用是弱引用。

        使用ARC的时候有两种命名规则需要注意:

   1. 属性名称不能以new开头,比如 @property NSString *newString是不被允许的。

   2. 属性不能只有一个read-only而没有内存管理特性。如果你没有启用ARC,可以使用@property (readonly) NSString *title语句,但如果你启用了ARC功能,就必须指定由谁来管理内存。因为默认的特性是assign,所以你可以进行一个简单的修复,使用unsafe_unretained就可以了。

同样的,强引用也有自己的_strong关键字和strong特性。需要注意,内存管理的关键字和特性是不能一起使用的,两者互相排斥。

 

   拥有者权限

 我们之前讨论过指针支持ARC的一个条件是必须是可保留对象指针(ROP)。这意味着,你不能简单地将一个ROP表示成不可保留对象指针(non-ROP),因为指针的所有权会移交。来看下面的代码。

  NSString *theString = @"Learn Objective-C";

 CFStringRef  cfString = (CFStringRef)theString;

如果你看过很多Objective-C代码,可能见过类似的结构。它在做什么?theString指针是一个ROP,而另一个CFStringRef则不是。为了让ARC便于工作,需要告诉编译器哪个对象是指针的拥有者,为此可以使用一种被称为桥接转换的C语言技术。这是一个标准的C语言类型转换,不过使用的是起亚关键字:_bridge , _bridge_retained和 _bridge_transfer。术语bridge指的是使用不同的数据类型达到同一目的的能力,而不是当你陷入ARC转换困境时帮你脱离困境的工具。以下是对这三种桥接转换的详细介绍:

(_bridge类型)操作符:这种类型的转换会传递指针但不会传递它的所有权。在前面的例子中,操作符是theString,而类型是CFStringRef。如果你使用了这个关键字,则一个指针是ROP,另一个不是。在这种情况下指针的所有权仍会留在操作符上。

   以下是使用了这种转换类型的代码示例:

  cfString = (_bridge CFStringRef)theString;

 cfString接收了命令,但指针的所有权仍然由theString保留。

(_bridge_retained类型)操作符:使用这种类型,所有权会转移到non-ROP上。与上一个相同,一个指针是ROP,另一个则不是。因为ARC只会注意到ROP,所以你要在不同的时候释放它。这个类型转换会给对象的保留计数器加1,所以你必须要让它减1,这与标准的内存管理方式相同。

以下是使用了这种转换类型的代码示例:

cfString = (_bridge_retained CFStringRef)theString

在这个示例中,cfString字符串拥有指针并且它的保留计数器加1.你要使用retain和release来管理它的内存。

(_bridge_transfer类型)操作符:这种类型转换与上一个相反,它把所有权转交给ROP。在这个示例中,ARC拥有对象并能确保它会向其他ARC对象一样得到释放。

另一个限制是结构体(struct)和集合体(union)不能使用ROP作为成员。因此下面这样的代码是不被允许的。

struct {

   int32_t fool;

char *bar;

NSString *baz;

}MyStruct;

你可以通过使用void*和桥接转换来解决这个问题。如果你想要分配并获取字符串,可以使用如下代码:

struct{

int32_t foo;

char *bar;

void *baz;

}MyStruct;

MyStruct.baz = (_bridge_retained void *)theString;

NSString *myString = (_bridge_transfer NSString *)MyStruct.baz;

如你所见,在两端的ARC代码并不总是自动编写的。

 

 

 

   

   

  

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值