Objective-C中,ARC下的 strong和weak指针原理解释

 

 

Objective-C中,ARC下的 strong和weak指针原理解释

提示:本文中所说的"实例变量"即是"成员变量","局部变量"即是"本地变量"

 

一、简介

ARC是自iOS 5之后增加的新特性,完全消除了手动管理内存的烦琐,编译器会自动在适当的地方插入适当的retain、release、autorelease语句。你不再需要担心内存管理,因为编译器为你处理了一切。

注意:ARC 是编译器特性,而不是 iOS 运行时特性(除了weak指针系统),它也不是类似于其它语言中的垃圾收集器。因此 ARC 和手动内存管理性能是一样的,有时还能更加快速,因为编译器还可以执行某些优化

 

二、原理

ARC 的规则非常简单:只要还有一个变量指向对象,对象就会保持在内存中。当指针指向新值,或者指针不再存在时,相关联的对象就会自动释放。这条规则对于实例变量、synthesize属性、局部变量都是适用的

 

三、strong指针

控制器中有个文本输入框框属性

@property (nonatomic, assign) IBOutlet UITextField *nameField;  

 

1.如果用户在文本框中输入mj这个字符串

那么就可以说,nameField的text属性是NSString对象的指针,也就是拥有者,该对象保存了文本输入框的内容。

 

2.如果执行了如下代码

   NSString *name = self.nameField.text;  

一个对象可以有多个拥有者,在上面代码中,name变量同样也是这个NSString对象的拥有者,也就是有两个指针指向同一个对象

 

3.随后用户改变了输入框的内容,比如

此时nameFeild的text属性就指向了新的NSString对象。但原来的NSString对象仍然还有一个所有者(name变量),因此会继续保留在内存中

 

4.当name变量获得新值,或者不再存在时(如局部变量方法返回时、实例变量对象释放时),原先的NSString对象就不再拥有任何所有者,retain计数降为0,这时对象会被释放

如,给name变量赋予一个新值

  name = @"Jake";  

 

 

我们称name和nameField.text指针为"Strong指针",因为它们能够保持对象的生命。默认所有实例变量和局部变量都是Strong指针。

 

四、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.subViews)拥有一个UITableView, UITableView的dataSource和delegate都是weak指针,指向你的ViewController

 

五、strong和weak指针的使用注意

1.下面代码是有问题的:

  __weak NSString *str = [[NSString alloc] initWithFormat:@"1234"];  

  NSLog(@"%@", str); // 打印出来是"(null)"  

str是个weak指针,所以NSString对象没有拥有者,在创建之后就会被立即释放。Xcode还会给出警告("Warning: Assigning retained object to weak variable; object will be released after assignment")

 

2.一般的指针变量默认就是strong类型的,因此一般我们对于strong变量不加__strong修饰,以下两行代码是等价的:

  NSString *name = self.nameField.text;  

  __strong NSString *name = self.nameField.text;  

 

3.属性可以是strong或weak,写法如下

  @property (nonatomic, strong) NSString *name;    

  @property (nonatomic, weak) id delegate;  


4.以下代码在ARC之前是可能会行不通的,因为在手动内存管理中,从NSArray中移除一个对象时,这个对象会发送一条release消息,可能会被立即释放。随后NSLog()打印该对象就会导致应用崩溃。(非ARC,需写作 id obj = [[array objectAtIndex:0] retain]; )

  id obj = [array objectAtIndex:0];  //从数组array中取出索引为0的对象,用obj变量来接收。

  [array removeObjectAtIndex:0];   //让array将索引为0的对象移除。(非ARC,加入array的对象,所有权交由数组来管理)

  NSLog(@"%@", obj);  

在ARC中这段代码是完全合法的,因为obj变量是一个strong指针,它成为了对象的拥有者,从NSArray中移除该对象也不会导致对象被释放。

  

六、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指针),但也没太大关系

 

七、ARC使用注意总结 

1.不能直接调用dealloc方法(也不能在dealloc方法里面去调[super dealloc]方法),不能调用retain,release,autorelease,retainCount方法,包括@selector(retain)的方式也不行;
2.可以用dealloc方法来管理一些资源,但不能用来释放实例变量如[self.name release],也不能在dealloc方法里面去掉[super dealloc]方法,在ARC下父类的dealloc同样由编译器来自动完成;
3.Core Foundation类型的对象仍然可以用CFRetain,CFRelease这些方法;
4.不能再使用NSAllocateObject和NSDeallocateObject对象;
5.不能在C结构体中使用对象指针,如果有类似功能可以创建一个Objective-C类来管理这些对象;
6.在id和void*之间没有简便的转换方法,同样在Objective-C和Core Foundation类型之间的转换都需要使用编译器制定的转换函数;
7.不能再使用NSAutoreleasePool对象,ARC提供了@autoreleasepool块来代替它,这样更有效率;
8.不能使用内存存储区(不能再使用NSZone);
9.不能以new为开头给一个属性命名;
10.声明IBOutlet时一般应当使用weak,除了对StoryBoard这样nib中间的顶层对象要用strong;
11.weak相当于老版本的assign,strong相当于retain。

转载于:https://www.cnblogs.com/stevenwuzheng/p/5358920.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/357400.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

elementui去掉表格所有边框

/deep/.el-table {border: 0;th,tr,td{border: 0;background-color: #fff;}&::before {height: 0px;}&::after {width: 0;}.el-table__fixed:before {height: 0;}}

cdi 2.7.5_集成测试CDI 1.0和Spring 3.1中的作用域bean

cdi 2.7.5在这篇博客文章中,我描述了如何在Spring和CDI中使用作用域bean进行集成测试。 一切都用小代码示例进行说明。 使用范围进行集成测试并不是特别容易。 想象一下存在于会话范围内的bean,例如UserCredentials 。 在集成测试中,通常没有…

工作流编写教程

介绍 ONES中使用了flowchart.js作为前端展示,并且扩展了flowchart.js的流程描述语言。flowchart.js 参见: https://github.com/adrai/flowchart.js 描述语言分为三部分,使用\n\n(空一行)作为分割,分别是节点定义、执行流程描述、节…

elementui设置表头与表格(左对齐,背景颜色,字体大小等)

headerStyle控制表头&#xff0c;finalCellStyle控制表格 html <div class"table1"><el-tablesize"mini":data"tableDataLeft"borderstripe:default-sort"defaultSort":max-height"tableMaxH":header-cell-style&…

使用LocalTestServer对HTTP调用进行单元测试

有时候&#xff0c;当您正在对远程服务器进行HTTP调用的单元测试代码时。 您可能正在使用诸如ApachesHttpClient或Spring的RestTemplate之类的库。 当然&#xff0c;您不想依靠远程服务进行单元测试。 除了涉及的开销&#xff08;记住单元测试应该是快速的&#xff09;之外&am…

PHP header函数大全

PHP header函数大全 header(Content-Type: text/html; charsetutf-8); header(Location: http://www.php-note.com/); <?php // fix 404 pages: header(HTTP/1.1 200 OK);// set 404 header: header(HTTP/1.1 404 Not Found);// set Moved Permanently header (good for re…

JS提升(hoisting)

近期在学习js&#xff0c;了解到js的一个名词&#xff0c;就是hoisting&#xff0c;进而了解了下js的解析机制 详情可参考&#xff1a;http://www.runoob.com/js/js-hoisting.html js的解析过程分为两个阶段&#xff1a;编译阶段和执行阶段 编译阶段&#xff1a;即我们常说的…

【Java从入门到天黑|01】SE入门之Java的前生今世

大家好,我是孙叫兽,微信公众号【孙叫兽杂谈】,本期给大家分享一下JavaSE的入门部分之Java的前生今世。 Java : 一个帝国的诞生 C语言帝国的统治 现在是公元1995年, C语言帝国已经统治了我们20多年, 实在是太久了。 1972年, 随着C语言的诞生和Unix的问世, 帝国

前端-html、css

HTML一、html简介超级文本标记语言是标准通用标记语言下的一个应用&#xff0c;也是一种规范&#xff0c;一种标准&#xff0c;它通过标记符号来标记要显示的网页中的各个部分。网页文件本身是一种文本文件&#xff0c;通过在文本文件中添加标记符&#xff0c;可以告诉浏览器如…

在Java EE组件中使用骆驼路线

从现在开始我一直在与Camel合作&#xff0c;我真的很喜欢它的简单性。 在Java EE之上始终使用它一直是一个挑战&#xff0c;而我最近发表的有关如何做到这一点的演讲之一以及Java EE中引导Camel的不同方法实际上建议使用WildFly-Camel Subsystem 。 在正在进行的系列文章中&…

【Java从入门到天黑|02】SE入门之Java基础

大家好,我是孙叫兽,微信公众号【孙叫兽杂谈】,本期给大家分享一下JavaSE的入门部分之Java基础 目录 注释 标识符 数据类型 类型转换 变量,常量 运算符

webpack入门

遇到问题首先到github项目的Issues中&#xff0c;检索一下相关问题&#xff0c;比在百度谷歌上直接搜索非官方解决方案好得多。 1、npm init 生成 package.json 2、npm i -D webpack 生成 # npm i -D 是 npm install --save-dev 的简写&#xff0c;是指安装模块并保存到 packa…

接口自动化 基于python+Testlink+Jenkins实现的接口自动化测试框架

基于pythonTestlinkJenkins实现的接口自动化测试框架 by:授客 QQ&#xff1a;1033553122 博客&#xff1a;http://blog.sina.com.cn/ishouke 欢迎加入软件性能测试交流QQ群&#xff1a;7156436 目录 1、 开发环境... 1 2、 主要功能逻辑介绍... 1 3、 框架…

PC钉钉无法输入汉字的解决办法

问题描述 新公司办公OA使用的钉钉&#xff0c;今天想给设计师发消息呢&#xff0c;发现私活输入不了汉字&#xff0c;早上还行呢&#xff0c; 过程尝试 在百度中可以输入汉字&#xff0c;在钉钉中不行。 解决办法 退出钉钉&#xff0c;重新进入&#xff0c;可以输入汉字了。如果…

this的指向

箭头函数&#xff1a;定义时所在的作用域&#xff08;tip:继承而来 函数作用域 &#xff09; 普通函数&#xff1a;指向调用它的对象 箭头函数体内的 this对象&#xff0c;就是定义时所在的对象&#xff0c;而不是使用时所在的对象 1、箭头函数没有自己的this&#xff0c;ar…

事关每个程序员的职业规划与履历

今天&#xff0c;甚至过去&#xff0c;大多数人都是由自己来设计他们的职业生涯的。 无论你正要启程&#xff0c;还是已经奋斗多年&#xff0c;以下内容都会对您的职业生涯有所助益。 目录 几条重要的职业规划提示。 1. 学习的步伐不停止 2. 学会问、学会听&#xff0c;学会学习…

iOS--viewController

隐藏状态栏 1 -(BOOL)prefersStatusBarHidden{ 2 return YES; 3 } 转载于:https://www.cnblogs.com/chebaodaren/p/5367160.html

jsf 开发_JSF开发人员应该知道的5种有用方法

jsf 开发这篇文章的目的是总结一些JSF开发人员可以在日常工作中使用的便捷方法。 实用程序类是将所有方法放在一起的好地方。 我会称此类为FacesAccessor。 第一种方法可能是最常用的方法。 它以给定名称返回托管bean。 必须按faces-config.xml或注释注册该bean。 注入是好的&a…

程序员应该如何规划自己的人生与书写履历?

今天,甚至过去,大多数人都是由自己来设计他们的职业生涯的。 无论你正要启程,还是已经奋斗多年,以下内容都会对您的职业生涯有所助益。几条重要的职业规划提示。1. 学习的步伐不停止 古人说,活到老,学到老。终身学习应该是您的座右铭。 世界在不断变化,每个人都在寻找各…

浅谈多线程——NSThread

上一篇文章中我们大致了解了GCD的模式和方法&#xff0c;在iOS开发中除了GCD之外&#xff0c;还有NSThread和NSOperation两种多线程方式。 1.NSThread - a - 使用NSThread开辟多线程进行子任务处理&#xff1a;类方法和初始化方法 使用类方法不需要创建对象就可以直接开辟多线程…