iOS编程:学习篇(五)

来源:互联网 发布:linux oracle安装教程 编辑:程序博客网 时间:2024/05/22 17:50

Chapter 3 通过ARC管理内存

当程序执行某个某方法时,会从内存中名为栈(stack)的区域分配一块内存空间,这块空间成为帧(frame)。帧负责保存程序在方法内声明的变量的值。

堆(heap)是指内存中的另一块区域,和栈是分开的。堆包含了大量无序的活动对象,需要通过指针来保存这些对象在堆中的地址。
当应用向某个类发送alloc消息时,系统会从堆中分配出一块内存,其大小足够存放相应对象的全部实例变量。iOS应用在启动和运行时会持续创建需要的对象,如果堆的空间无限,则可以随意创建所需的对象,并且在应用运行时间不用释放。但是可供应用支票的堆空间是有限的。因此再需要某些对象时,就要将其释放掉。

指针变量与对象所有权

指针变量暗含了对其所指向的对象的所有权。

  • 当某个方法有一个指向某个对象的局部变量时,可以称该变量拥有变量所指向的对象
  • 当某个对象有一个指向其他对象的实例变量时,可以称该对象拥有该实例变量所指向的对象。

对象所有权概念可以帮助我们决定是否应该释放某个对象并回收该对象占有的内存。

  • 如果某个对象没有拥有者,就应该将其释放掉。没有拥有者的对象是孤立的,程序无法向其发送消息。保留这样的对象只回浪费宝贵的内存空间,导致内存泄露(memory leap)。
  • 如果某个对象有一个或多个拥有者,就必须保留不能释放。如果释放了某个对象,但是其他对象或方法仍然有指向对象的指针,那么想该指针指向的对象发送消息就会使应用崩溃。释放正在使用的对象的错误成为过早释放。指向不存在对象的指针称为空指针(danging pointer)或者空引用(danging reference)。

    哪些情况会使对象失去拥有者

  • 当程序修改某个指向特定对象的变量并将其指向另一个对象时。

  • 当程序将某个特定对象的变量设置为nil。
  • 当程序释放对象的某个拥有者时。
    方法或函数可以通过局部变量成为对象的拥有者。当程序执行完某个方法,将其帧弹出栈时,就会释放该方法的所有局部变量。在这些变量中,如果有指向其他的对象的指针变量,那么这些对象就会失去一个拥有者。
  • 当从collection类中删除对象时。

所有权链(ownership chains)

因为对象可以拥有其他对象,后者也可以再拥有别的对象,所以释放一个对象可能会产生连锁反应,导致多个对象失去拥有者,进而释放对象并归还内存。

强引用与弱引用

只要指针指向了某个对象,那么相应的对象就会多一个拥有者,并且不会被程序释放。这种指针特性称为强引用(strong reference)
程序也可以选择让指针变量不影响其指向对象的拥有者个数。这种不会改变对象拥有者个数的指针特性称为弱引用(weak reference)

强引用循环(strong reference cycle 或 保留循环):当两个或两个以上的对象相互之间有强引用特性的指针关联时,就会产生强引用循环。

将强引用循环解除前,需要将新创建的两个对象之间某个指针改为弱引用特性。在决定将哪个指针改为弱引用前,可以先为存在强引用循环问题的多个对象决定相应的父子关系。确定父子关系后,就可以让父对象拥有子对象,并确保不会拥有负对象。
通常情况下,父对象应该使用工具有强引用特性的指针,指向子对象。而子对象则应该使用具有弱引用特性的指针,指回父对象。如果某个子对象需要有一个指针,指向父对象的父对象,那么该指针必须具有弱引用特性。

属性

通过属性也可以为类声明实例变量并实现相应的存取方法。
声明一个属性,等于隐含地为相应名称的实例变量声明一对存取方法。

属性的名字是实例变量的名字去掉下划线,编译器根据属性生成实例变量时会自动在变量名加上下划线。声明属性还可以为相应的存取方法生成代码。

属性的特性

任何属性都可以有一组特性(attribute),用于描述相应存取方法的行为。

在Xcode4.5及以后的版本中,可以省略@synthesize ,编译器会自动帮你加上getter 和 setter 方法的实现,并且默认会去访问_age这个成员变量,如果找不到_age这个成员变量,会自动生成一个叫做 _age的私有成员变量。

0 0
原创粉丝点击