• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号
您的位置:首页 > 程序设计 >C语言 > 《Objective-C高级编程》干货三部曲(一):引用计数篇

《Objective-C高级编程》干货三部曲(一):引用计数篇

作者:孙世杰的博客 字体:[增加 减小] 来源:互联网 时间:2017-07-23

孙世杰的博客通过本文主要向大家介绍了ios,objective-c等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

总结了Effective Objective-C之后,还想读一本进阶的iOS书,毫不犹豫选中了《Objective-C 高级编程》:

《Objective-C高级编程:iOS与OS X多线程和内存管理》

这本书有三个章节,我针对每一章节进行总结并加上适当的扩展分享给大家。可以从下面这张图来看一下这三篇的整体结构:

《Objective-C高级编程》 干货三部曲

注意,这个结构并不和书中的结构一致,而是以书中的结构为参考,稍作了调整。

本篇是第一篇:引用计数,简单说两句:
Objective-C通过 retainCount 的机制来决定对象是否需要释放。 每次runloop迭代结束后,都会检查对象的 retainCount,如果retainCount等于0,就说明该对象没有地方需要继续使用它,可以被释放掉了。无论是手动管理内存,还是ARC机制,都是通过对retainCount来进行内存管理的。

先看一下手动内存管理:

手动内存管理

我个人觉得,学习一项新的技术之前,需要先了解一下它的核心思想。理解了核心思想之后,对技术点的把握就会更快一些:

内存管理的思想

  • 思想一:自己生成的对象,自己持有。
  • 思想二:非自己生成的对象,自己也能持有。
  • 思想三:不再需要自己持有的对象时释放对象。
  • 思想四:非自己持有的对象无法释放。

从上面的思想来看,我们对对象的操作可以分为三种:生成,持有,释放,再加上废弃,一共有四种。它们所对应的Objective-C的方法和引用计数的变化是:

对象操作 Objecctive-C方法 引用计数的变化
生成并持有对象 alloc/new/copy/mutableCopy等方法 +1
持有对象 retain方法 +1
释放对象 release方法 -1
废弃对象 dealloc方法 无

用书中的图来直观感受一下这四种操作:

图片来自:《Objective-C高级编程:iOS与OS X多线程和内存管理》

下面开始逐一解释上面的四条思想:

思想一:自己生成的对象,自己持有

在生成对象时,使用以下面名称开头的方法生成对象以后,就会持有该对象:

  • alloc
  • new
  • copy
  • mutableCopy

举个??:

id obj = [[NSObject alloc] init];//持有新生成的对象

这行代码过后,指向生成并持有[[NSObject alloc] init]的指针被赋给了obj,也就是说obj这个指针强引用[[NSObject alloc] init]这个对象。

同样适用于new方法:

id obj = [NSObject new];//持有新生成的对象

注意:
这种将持有对象的指针赋给指针变量的情况不只局限于上面这四种方法名称,还包括以他们开头的所有方法名称:
- allocThisObject
- newThatObject
- copyThisObject
- mutableCopyThatObject

举个??:

id obj1 = [obj0 allocObject];//符合上述命名规则,生成并持有对象

它的内部实现:

- (id)allocObject
{
    id obj = [[NSObject alloc] init];//持有新生成的对象
    return obj;
}

反过来,如果不符合上述的命名规则,那么就不会持有生成的对象,
看一个不符合上述命名规则的返回对象的createObject方法的内部实现??:

- (id)createObject
{
    id obj = [[NSObject alloc] init];//持有新生成的对象
    [obj autorelease];//取得对象,但自己不持有
    return obj;
}

经由这个方法返回以后,无法持有这个返回的对象。因为这里使用了autorelease。autorelease提供了这样一个功能:在对象超出其指定的生存范围时能够自动并正确地释放(详细会在后面介绍)。

图片来自:《Objective-C高级编程:iOS与OS X多线程和内存管理》

也就是说,生成一个调用方不持有的对象是可以通过autorelease来实现的(例如NSMutableArray的array类方法)。

我的个人理解是:通过autorelease方法,使对象的持有权转移给了自动释放池。所以实现了:调用方拿到了对象,但这个对象还不被调用方所持有。

由这个不符合命名规则的例子来引出思想二:

思想二:非自己生成的对象,自己也能持有

我们现在知道,仅仅通过上面那个不符合命名规则的返回对象实例的方法是无法持有对象的。但是我们可以通过某个操作来持有这个返回的对象:这个方法就是通过retain方法来让指针变量持有这个新生成的对象:

id obj = [NSMutableArray array];//非自己生成并持有的对象
[obj retain];//持有新生成的对象

注意,这里[NSMutableArray array]返回的非自己持有的对象正是通过上文介绍过的autorelease方法实现的。所以如果想持有这个对象,需要执行retain方法才可以。

思想三:不再需要自己持有的对象时释放对象

对象的持有者有义务在不再需要这个对象的时候主动将这个对象释放。注意,是有义务,而不是有权利,注意两个词的不同。

来看一下释放对象的例子:

id obj = [[NSObject alloc] init];//持有新生成的对象
[obj doSomething];//使用该对象做一些事情
[obj release];//事情做完了,释放该对象

同样适用于非自己生成并持有的对象(参考思想二):

id obj = [NSMutableArray array];//非自己生成并持有的对象
[obj retain];//持有新生成的对象
[obj soSomething];//使用该对象做一些事情
[obj release];//事情做完了,释放该对象

可能遇到的面试题:调用对象的release方法会销毁对象吗?
答案是不会:调用对象的release方法只是将对象的引用计数器-1,当对象的引用计数器为0的时候会调用了对象的dealloc 方法才能进行释放对象的内存。

思想四:无法释放非自己持有的对象

在释放对象的时候,我们只能释放已经持有的对象,非自己持有的对象是不能被自己释放的。这很符合常识:就好比你自己才能从你自己的银行卡里取钱,取别人的卡里的钱是不对的(除非他的钱归你管。。。只是随便举个例子)。

两种不允许的情况:

分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • 《Objective-C高级编程》干货三部曲(一):引用计数篇
  • 简单谈谈C++ 头文件系列之(iosfwd)
  • 总结IOS中nil、Nil、NULL和NSNull区别
  • Cocos2d-x UI开发之CCControlPotentiometer控件类使用实例
  • Cocos2d-x UI开发之CCControlSwitch控件类使用实例
  • Cocos2d-x UI开发之CCControlColourPicker控件类使用实例
  • Cocos2d-x UI开发之CCControlSlider控件类使用实例
  • Cocos2d-x UI开发之CCControlButton控件类实例
  • iostream与iostream.h的区别详细解析
  • 基于ios中的流状态的定义分析

相关文章

  • 2017-05-28STl中的排序算法详细解析
  • 2017-05-28C++实现多线程查找文件实例
  • 2017-05-28使用C语言解决字符串全排列问题
  • 2017-05-28Windows程序内部运行机制实例详解
  • 2017-05-28C++ 构造函数中使用new时注意事项
  • 2017-05-28C++中的异或运算符^的使用方法
  • 2017-05-28VC++实现通过API来查看程序错误信息的方法
  • 2017-05-28深入学习C语言中的函数指针和左右法则
  • 2017-05-28C语言中fgetgrent()函数和fgetpwent()函数的用法对比
  • 2017-05-28详解C语言中strpbrk()函数的用法

文章分类

  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号

最近更新的内容

    • 基于C++中常见编译错误的总结详解
    • 使用C语言打造通讯录管理系统和教学安排系统的代码示例
    • 使用C++实现全排列算法的方法详解
    • C++编程中将引用类型作为函数参数的方法指南
    • 使用钩子如何锁定键盘的方法分享
    • assert断言函数
    • C语言 指针数组详解及示例代码
    • javascript 两种声明函数的方式的分析
    • 引用参数和传值参数的区别深入解析
    • 冒泡排序的三种实现方法

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有