提示:本文中所说的"实例变量"便是"成员变量","局部变量"便是"本地变量"html
1、简介java
ARC是自iOS 5以后增长的新特性,彻底消除了手动管理内存的烦琐,编译器会自动在适当的地方插入适当的retain、release、autorelease语句。你再也不须要担忧内存管理,由于编译器为你处理了一切ios
注意:ARC 是编译器特性,而不是 iOS 运行时特性(除了weak指针系统),它也不是垃圾收集器。所以 ARC 和手动内存管理性能是同样的,有时还能更加快速,由于编译器还能够执行某些优化objective-c
2、原理app
ARC 的规则很是简单:只要有变量指向对象,对象就会存在内存。当指针指向新值,或者指针再也不存在时,相关联的对象就会自动释放。这条规则对于实例变量、synthesize属性、局部变量都是适用的ide
3、strong指针函数
控制器中有个文本输入框框属性工具
1.若是用户在文本框中输入mj这个字符串oop
那么就能够说,nameField的text属性是NSString对象的指针,也就是拥有者,该对象保存了文本输入框的内容post
2.若是执行了以下代码
3.随后用户改变了输入框的内容,好比
此时nameFeild的text属性就指向了新的NSString对象。但原来的NSString对象仍然还有一个全部者(name变量),所以会继续保留在内存中
4.当name变量得到新值,或者再也不存在时(如局部变量方法返回时、实例变量对象释放时),原先的NSString对象就再也不拥有任何全部者,retain计数降为0,这时对象会被释放
如,给name变量赋予一个新值
咱们称name和nameField.text指针为"Strong指针",由于它们可以保持对象的生命。默认全部实例变量和局部变量都是Strong指针
4、weak指针
weak型的指针变量仍然能够指向一个对象,但不属于对象的拥有者
1.执行下面的代码
__weak NSString *name = self.nameField.text;
name变量和nameField.text属性都指向同一个NSString对象,但name不是拥有者
2.若是文本框的内容发生变化,则原先的NSString对象就没有拥有者,会被释放,此时name变量会自动变成nil,称为空指针
weak型的指针变量自动变为nil是很是方便的,这样阻止了weak指针继续指向已释放对象,避免了野指针的产生,否则会致使很是难于寻找的Bug,空指针消除了相似的问题
3.weak指针主要用于“父-子”关系,父亲拥有一个儿子的strong指针,所以父亲是儿子的全部者;但为了阻止全部权循环,儿子须要使用weak指针指向父亲。典型例子是delegate模式,你的ViewController经过strong指针(self.view)拥有一个UITableView, UITableView的dataSource和delegate都是weak指针,指向你的ViewController
5、strong和weak指针的使用注意
1.下面代码是有问题的:
2.通常的指针变量默认就是strong类型的,所以通常咱们对于strong变量不加__strong修饰,如下两行代码是等价的:
3.属性能够是strong或weak,写法以下
6、ARC小结
1.有了ARC,咱们的代码能够清晰不少,你再也不须要考虑何时retain或release对象。惟一须要考虑的是对象之间的关联,也就是哪一个对象拥有哪一个对象?
2.ARC也有一些限制:
1> 首先ARC只能工做于Objective-C对象,若是应用使用了Core Foundation或malloc()/free(),此时仍是须要你来手动管理内存
2> 此外ARC还有其它一些更为严格的语言规则,以确保ARC可以正常地工做
3.虽然ARC管理了retain和release,但并不表示你彻底不须要关心内存管理的问题。由于strong指针会保持对象的生命,某些状况下你仍然须要手动设置这些指针为nil,不然可能致使应用内存不足。不管什么时候你建立一个新对象时,都须要考虑谁拥有该对象,以及这个对象须要存活多久
4.ARC还能很好地结合C++使用,这对游戏开发是很是有帮助的。对于iOS 4,ARC有一点点限制(不支持weak指针),但也没太大关系
7、ARC使用注意总结
要想将非ARC的代码转换为ARC的代码,大概有2种方式:
1.使用Xcode的自动转换工具
2.手动设置某些文件支持ARC
1、Xcode的自动转换工具
Xcode带了一个自动转换工具,能够将旧的源代码转成ARC模式
1.ARC是LLVM 3.0编译器的特性,而现有工程可能使用老的GCC 4.2或LLVM-GCC编译器,所以首先须要设置使用LLVM 3.0编译器:
(现使用的XCode4.5,LLVM 3.0已经升级到LLVM 4.1)
最好也选上Warnings中的Other Warning Flags 为 -Wall,这样编译器就会检查全部可能的警告,有助于咱们避免潜在的问题
2.Build Options下面的Run Static Analyzer选项也最好启用,这样每次Xcode编译项目时,都会运行静态代码分析工具来检查咱们的代码
3.设置"Objective-C Automatic Reference Counting"选项为YES,不过Xcode自动转换工具会自动设置这个选项,这里只是说明一下如何手动设置
4.打开Xcode的自动转换工具
5.Xcode会显示一个新窗口,让你选择哪些文件须要转换
点击Check按钮,Xcode可能会弹出对话框提示项目不能转换为ARC,须要你准备好转换(这里暂时省略详细说明)
6.若是没有什么警告、错误了,就会弹出一下提示窗口:
7.点击Next,几秒钟后,Xcode会提示全部文件的转换预览,显示源文件的全部改变。左边是修改后的文件,右边是原始文件。在这里你能够一个文件一个文件地查看Xcode的修改,以确保Xcode没有改错你的源文件:
点击Save便可完成转换
8.自动转换以后,Xcode会移除全部retain、release、autorelease调用,这可能会致使代码出现其它警告、无效语法等,这些都须要本身手工进行修改
注意:Xcode的自动转换工具最好只使用一次,屡次使用可能会出现比较诡异的问题。假如你第一次转换没有转换全部的文件,当你稍后试图再次转换剩余的文件时,Xcode实际上不会执行任何转换操做。所以最好一次就完成转换,没有转换的文件能够考虑手工进行修改
2、手动开启某些文件的ARC
在Compiler Flags一列加上-fobjc-arc就表示开启这个.m文件的ARC
3、禁止某些文件的ARC
在Compiler Flags一列加上-fno-objc-arc就表示禁止这个.m文件的ARC
本章介绍引入ARC后@property的使用,跟ARC以前的仍是很不同的
1、.h和.m文件的变化说明
1.对于.h头文件,主要是将属性定义由retain变为strong
咱们能够直接在.m类实现中定义private实例变量,没必要写分类拓展了:
在ARC中,全部IBOutlet属性都推荐使用weak, 这些view对象已经属于View Controller的view hierarchy,不须要再次定义为strong。所以,这些定义为weak的IBOutlet属性都不须要在IBOutlet中设置为nil
3、@property的修饰符小结
• strong : 该属性值对应 __strong 关键字,即该属性所声明的变量将成为对象的持有者,等同于"retain"
• weak : 该属性对应 __weak 关键字,与 __weak 定义的变量一致,该属性所声明的变量将没有对象的全部权,而且当对象被释放以后,对象将被自动赋值nil,记住IBOutlet应该使用weak
• unsafe_unretained : 等效于__unsafe_unretaind关键字声明的变量,等同于以前的"assign",iOS 5以前的系统用该属性代替 weak 来使用
• copy : 和以前的copy同样,复制一个对象并建立strong关联
• assign : 对象不能使用assign,但原始类型(BOOL、int、float)仍然可使用
先一句话总结:strong类保持他们拥有对象的活着,weak类他们拥有的对象被人家一牵就牵走,被人家一干就干死。(strong是一个好大哥因此strong,呵呵,weak是一个虚大哥因此weak,呵呵)
好比有一个对象是string类,实例是@“hello”
现有两个strong的string指针大哥a和b都指向了hello,如今b大哥把改为了指向@“hi”。那么这时候a大哥指向的值是什么呢,答案仍是“hello”。而后,a大哥看hi不错,也指向了hi,那么如今hello就被都抛弃了,也就从内存中删除了。由于a大哥是strong的,既是retain或者copy的,这两个东西是可使对象保存在计算机内存里的,因此若是即便b大哥抛弃hello,a大哥是有资本使@“hello”继续活下去。
而如今又有两个对象strong的c大哥和weak的d大哥,都指向hello,如今c大哥另有所爱,指向了以前的b大哥,同时a大哥也指向了b大哥,既如今没有strong大哥指向hello。那么如今这个weak的d大哥指向的对象就是一个屁啦,既nil。
标签: objective-cit |
写这篇文章的原因,是由于我泡在stackoverflow上翻帖子,看到一个名为Should IBOutlets be strong or weak under ARC? 的帖子很热,而我对被采纳为标准答案的回答也有一些话要补充,我想对于每个初识ARC模式的人来讲,都会有这个疑问,因此不妨我也来和你们探讨一下。
有人问,在ARC下,IBOutlets到底应该定义成strong 仍是 weak ?支持这个答案的人最多,答案仅是摘自官方文档的一个片断:
From a practical perspective, in iOS and OS X outlets should be defined as declared properties. Outlets should generally be weak, except for those from File’s Owner to top-level objects in a nib file (or, in iOS, a storyboard scene) which should be strong. Outlets that you create will therefore typically be weak by default, because:
Outlets that you create to, for example, subviews of a view controller’s view or a window controller’s window, are arbitrary references between objects that do not imply ownership.
The strong outlets are frequently specified by framework classes (for example, UIViewController’s view outlet, or NSWindowController’s window outlet).
@property (weak) IBOutlet MyView *viewContainerSubview; @property (strong) IBOutlet MyOtherClass *topLevelObject;
大意是说,在 ARC 中,通常outlet属性都推荐使用 weak,应该使用 strong 的 outlet 是 File's Owner链接到 nib 的顶层对象。
什么是 File's Owner链接到 nib 的顶层对象呢?说白话一点,就是自定义的view,不是直接做为main view里面一个sub view直接显示出来,而是须要经过实例化建立出来的。你本身实例化,固然须要strong了,否则谁还替你保留对象全部权呢?
以上的分析都没有错,可是总以为少了点什么。对于究竟是weak 仍是 strong,归根结底,仍是要刨到对对象全部权的问题上,可是不便于总结出浅显易懂的规律性使用法则。因而,就会有一个又一个的特例打破文档所总结的常规,不明白规则的根是什么,仍是会碰到麻烦的。
我来举一个简单的例子,建立一个程序入口指向navigation controller的工程,导航栏上拖2个按钮:
右侧按钮用于控制相机按钮的显示与否,按照文档的指示,咱们在程序中定义这两个按钮应为weak属性
用右侧按钮,控制相机按钮的隐藏和显示:
实验结果是,第一次隐藏了相机按钮后,就再也显示不出来了。缘由很简单,cameraBtn指向了空,咱们丢失了cameraBtn的对象全部权。
解决问题的办法有两个:
1.不在xib或者storyboard上拖相机按钮,而是用代码建立,本身控制对象全部权
2.将 cameraBtn 定义为strong
我想强调的固然是第二种方法,固然了,改为strong后,相应的也须要配合ARC作下工做:
顺便提一下ARC其余属性的规则:
strong:等同于"retain",属性成为对象的拥有者
weak:属性是 weak pointer,当对象释放时会自动设置为 nil
unsafe_unretained:等同于以前的"assign",只有 iOS 4 才应该使用
copy:和以前的 copy 同样,复制一个对象并建立 strong 关联
assign:对象不能使用 assign,但原始类型(BOOL、int、float)仍然可使用
最后一句,记忆规则,理解规则,善用规则。