文档章节

“自释放”在iOS开发中的应用

木木情深
 木木情深
发布于 2015/06/24 16:38
字数 1437
阅读 30
收藏 0
点赞 0
评论 0

对象内存的回收


开发中,对象管理的基本原则——谁创建谁释放。但是,非ARC工程中,我们会用autorelease来标记一个对象,告诉编辑器,这个对象我不负责释放,此时,这个对象就变成了“自释放”对象,当其不再需要时,系统就会自动回收其内存。而ARC工程中,所有对象对于我们来说都是自释放对象,很高兴,我们不再需要处处留意内存泄露的问题,可以把更多的精力放在业务逻辑上,但是这并不意味着真的没有内存泄露,试试这个工具HJNSObjectRelease,也许你会有意想不到的收获。


定时器的自释放

定时器与一般对象不同,当创建完定时器后,其并不会自我释放,需要在适当时刻invalidate。在实际开发中,也许你经常会这样创建定时器

self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(onTimerCount) userInfo:nil repeats:YES];

然后在dealloc函数中将定时器invalidate。很遗憾,你会发现程序永远也不会执行到dealloc函数,因为NSTimer强引用target对象,循环引用的出现必然导致内存泄露。此时,你肯定非常想要一个weak target的定时器,很高兴, MSWeakTimer 很好的满足了你的需求。但是,Timer仍然没有自我释放,你仍然需要在dealloc中将其invalidate。那么,如何才能不写invalidate?定时器能否自释放?我们先把这个问题放在一边,接着往下看


KVO的自释放

iOS开发中,经常会用到消息通知及KVO,也许你会这样写代码


- (void)viewDidLoad {

    [super viewDidLoad];

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onNotice) name:@"NoticeIdentifier" object:nil];

    [self addObserver:target forKeyPath:@"keyPath" options:NSKeyValueObservingOptionNew context:nil];

}

- (void)dealloc {

    [[NSNotificationCenter defaultCenter] removeObserver:self name:@"NoticeIdentifier" object:nil];

    [self removeObserver:target forKeyPath:@"keyPath"];

}

随着时间的积累,你会非常习惯这种写法,并且苹果也是这样推荐的。但是慢慢你会发现所有对象的Dealloc函数都只做了这一件事,能不能不做这件事? FBKVOController 也许会是一个不错的选择,Demo可以这样写


[self.KVOController observe:clock keyPath:@"date" options:NSKeyValueObservingOptionInitial|NSKeyValueObservingOptionNew block:^(ClockView *clockView, Clock *clock, NSDictionary *change) {

    clockView.date = change[NSKeyValueChangeNewKey];

}];

FBKVOController 的实现原理可以查看这篇 文章 ,通过自释放的实现,程序猿不再关心remove监听。但是其还是有一定的局限性——对象无法监听自己的属性,如果你的代码是这样的


[self.KVOController observe:self keyPath:@"date" options:NSKeyValueObservingOptionNew block:^(NSDictionary *change) {

    // to do

}];

很遗憾,循环引用的问题又出现,因为 FBKVOController 中的NSMapTable对象会retain key对象,具体代码如下


[_objectInfosMap setObject:infos forKey:object];

那么, FBKVOController 是如何做到自释放的?可以归纳为四个字——动态属性。其为观察者绑定动态属性self.KVOController,动态绑定的KVOController会随着观察者的释放而释放,KVOController在自己的dealloc函数中移除KVO监听,巧妙的将观察者的remove转移到其动态属性的dealloc函数中。


可是,这又有什么用?对象仍然无法监听自己的属性,还是要重写set函数。 HTBKVObservation 也许会改变你的想法,其和 FBKVOController 来自同一人,代码可以这样写


self.anObservation = [HTBKVObservation observe:anObjectToObserve keyPath:@"observeMe" options:0 callback:^(HTBKVObservation *observation, NSDictionary *changeDictionary) {

   // to do

}];

HTBKVObservation 并没用采用动态属性,而是采用属性的方式实现自释放。可以监控对象自己的属性,但是需要创建属性HTBKVObservation。 这里 我对其做了一点扩展,方便使用,代码可以这样写


[self observe:self keyPath:@"KVOPath" options:NSKeyValueObservingOptionNew callback:^(HTBKVObservation *observation, NSDictionary *changeDictionary) {

   // to do

}];

FBKVOController 和 HTBKVObservation 通过属性或动态属性巧妙的将KVO的remove转移给第三者,实现了KVO事件的解耦,为自释放的实现提供了一种借鉴思路


NSNotification的自释放


谈完 KVO,再来谈谈NSNotification。针对Notification, ReactiveCocoa 做了很好的封装,网上有很多介绍其如何使用的文章,在此不再累述。直接看代码


[[[NSNotificationCenter defaultCenter] rac_addObserverForName:UIKeyboardDidChangeFrameNotification object:nil] subscribeNext:^(id x) {

        // to do

    }

];

简单明了,当观察者dealloc,很遗憾,NSNotification并没用移除,因为对象并没用自释放,正确代码应该是这样


[[[[NSNotificationCenter defaultCenter] rac_addObserverForName:UIKeyboardDidChangeFrameNotification object:nil] takeUntil:self.rac_willDeallocSignal] subscribeNext:^(id x) {

        // to do

    }

];

ReactiveCocoa 自释放的原理与 FBKVOController 不同,其并不是通过属性或者动态属性的方式实现,而是通过swizzling观察对象的dealloc函数,在自定义dealloc函数实施清理,但不是默认清理,需要我们告诉它willDeallocSignal的时候完成所有清理工作。


除了定时器、KVO、NSNotification,包括封装的某个功能对象,比如HttpRequest,或者数据库ListSql等,合理的利用自释放可以给使用者带来更多的便利,同时也会减少 crash 产生的概率。实现自释放的方法可以总结为以下三种方式


动态属性的自释放

@property 的自释放

swizzling dealloc的自释放

可以根据具体业务或者设计思想选择对应的实现方式,这是一种思想,更是一个习惯。相信你会爱上它,毕竟谁不喜欢简洁的实现方式了!


© 著作权归作者所有

共有 人打赏支持
木木情深
粉丝 37
博文 186
码字总数 26451
作品 0
广州
程序员
【AR】开始使用Vuforia开发iOS(2)

原 设置iOS开发环境 安装Vuforia iOS SDK 如何安装Vuforia iOS示例 编译并运行Vuforia iOS示例 支持iOS金属 iOS 64位迁移 设置iOS开发环境 适用于iOS的Vuforia引擎目前支持运行iOS 9及更高版...

lichong951 ⋅ 06/11 ⋅ 0

iOS逆向工程- 学习整理(工具详解)

前言 一、逆向工程的要求 具备丰富的 iOS 开发经验 最好能非常熟悉 iOS 设备的硬件构成,iOS 系统的运行原理。 拿到任意一个 App 之后能够大致推断出它的项目规模和使用的技术,比如它的MVC模...

_小迷糊 ⋅ 05/11 ⋅ 0

面试官自述:面向高级开发人员的iOS面试问题

当您准备进行技术性iOS面试时,了解您可能会询问哪些主题以及经验丰富的iOS开发人员期望什么是非常重要的。 这是许多硅谷公司用来衡量iOS候选人资历水平的一系列问题。 这些问题涉及iOS开发的...

菇哒微课 ⋅ 04/26 ⋅ 0

2018 一份"有点难"的iOS面试题(5年iOS开发)

序言: 之前一时兴致在本站上出过一份iOS的中级面试题,引起一些关注,不少同学表示对”隐藏关卡“感兴趣。升级版iOS面试题来了,目测难倒90%iOS程序员,目测一大波程序员撸着袖子在靠近。 ...

原来是泽镜啊 ⋅ 05/26 ⋅ 0

挖掘安卓宝藏,EMUI会让手机进入“量心定制”时代吗?

如果把移动终端的发展历程看做一部戏剧,那么Android和iOS两种操作系统生态之间的竞争一定是最精彩的一折。 从市场占有率来看,2017年Android手机在全球售出的手机中占据了85.9%份额,其中自...

脑极体 ⋅ 04/17 ⋅ 0

人民日报:让芯片、操作系统不再有"卡脖子"隐忧

人民日报:让芯片、操作系统不再有"卡脖子"隐忧 2018-04-25 12:28编辑: suiling分类:业界动态来源:人民日报 操作系统iOS芯片安卓自主创新 招聘信息: C++工程师 Cocos2d-x游戏客户端开发 ...

suiling ⋅ 04/25 ⋅ 0

人工智能要成精了?英伟达展示逆天修图技术

人工智能要成精了?英伟达展示逆天修图技术 2018-04-25 12:03编辑: 枣泥布丁分类:AI来源:青亭网 英伟达人工智能PS 招聘信息: C++工程师 Cocos2d-x游戏客户端开发 iOS开发工程师 京东招聘...

枣泥布丁 ⋅ 04/25 ⋅ 0

如何做好iOS应用安全?这有一把行之有效的“三板斧”

本文由 网易云 发布 iOS应用面临很多破解问题,常见的有IAP内购破解、山寨版本、破解版本等;大众应用上,微信抢红包、微信多开等;而在iOS游戏上,越来越泛滥的外挂问题也不断困扰着游戏厂商...

wangyiyungw ⋅ 05/15 ⋅ 0

如何判断你是合格的高级iOS开发工程师?

前言 随着移动互联网的高速发展泄洪而来,有意学习移动开发的人越来越多了,竞争也是越来越大,需要学习的东西很多。如何才能在激烈的移动开发者竞争中一枝独秀,成为一名真正合格的高级iOS...

_小迷糊 ⋅ 05/26 ⋅ 0

多伦多大学开发反面部识别系统 人脸识别率降至0.5%

多伦多大学开发反面部识别系统 人脸识别率降至0.5% 2018-06-06 13:30编辑: CuiTong分类:AI来源:青亭网 人工智能AI反面部识别 招聘信息: C++工程师 Cocos2d-x游戏客户端开发 iOS开发工程师...

CuiTong ⋅ 06/06 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

笔试题之Java基础部分【简】【一】

基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语法,集合的语法,io 的语法,虚拟机方面的语法,其他 1.length、length()和size() length针对...

anlve ⋅ 21分钟前 ⋅ 1

table eg

user_id user_name full_name 1 zhangsan 张三 2 lisi 李四 `` ™ [========] 2018-06-18 09:42:06 星期一½ gdsgagagagdsgasgagadsgdasgagsa...

qwfys ⋅ 46分钟前 ⋅ 0

一个有趣的Java问题

先来看看源码: public class TestDemo { public static void main(String[] args) { Integer a = 10; Integer b = 20; swap(a, b); System.out......

linxyz ⋅ 50分钟前 ⋅ 0

十五周二次课

十五周二次课 17.1mysql主从介绍 17.2准备工作 17.3配置主 17.4配置从 17.5测试主从同步 17.1mysql主从介绍 MySQL主从介绍 MySQL主从又叫做Replication、AB复制。简单讲就是A和B两台机器做主...

河图再现 ⋅ 今天 ⋅ 0

docker安装snmp rrdtool环境

以Ubuntu16:04作为基础版本 docker pull ubuntu:16.04 启动一个容器 docker run -d -i -t --name flow_mete ubuntu:16.04 bash 进入容器 docker exec -it flow_mete bash cd ~ 安装基本软件 ......

messud4312 ⋅ 今天 ⋅ 0

OSChina 周一乱弹 —— 快别开心了,你还没有女友呢。

Osc乱弹歌单(2018)请戳(这里) 【今日歌曲】 @莱布妮子 :分享吴彤的单曲《好春光》 《好春光》- 吴彤 手机党少年们想听歌,请使劲儿戳(这里) @clouddyy :小萝莉街上乱跑,误把我认错成...

小小编辑 ⋅ 今天 ⋅ 8

Java 开发者不容错过的 12 种高效工具

Java 开发者常常都会想办法如何更快地编写 Java 代码,让编程变得更加轻松。目前,市面上涌现出越来越多的高效编程工具。所以,以下总结了一系列工具列表,其中包含了大多数开发人员已经使用...

jason_kiss ⋅ 昨天 ⋅ 0

Linux下php访问远程ms sqlserver

1、安装freetds(略,安装在/opt/local/freetds 下) 2、cd /path/to/php-5.6.36/ 进入PHP源码目录 3、cd ext/mssql进入MSSQL模块源码目录 4、/opt/php/bin/phpize生成编译配置文件 5、 . ./...

wangxuwei ⋅ 昨天 ⋅ 0

如何成为技术专家

文章来源于 -- 时间的朋友 拥有良好的心态。首先要有空杯心态,用欣赏的眼光发现并学习别人的长处,包括但不限于工具的使用,工作方法,解决问题以及规划未来的能力等。向别人学习的同时要注...

长安一梦 ⋅ 昨天 ⋅ 0

Linux vmstat命令实战详解

vmstat命令是最常见的Linux/Unix监控工具,可以展现给定时间间隔的服务器的状态值,包括服务器的CPU使用率,内存使用,虚拟内存交换情况,IO读写情况。这个命令是我查看Linux/Unix最喜爱的命令...

刘祖鹏 ⋅ 昨天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部