iOS 循环引用 委托 (实例说明)
如何避免循环引用造成的内存泄漏呢:
以delegate模式为例(viewcontroller和view之间就是代理模式,viewcontroller有view的使用权,viewcontroller同时也是view的代理(处理view中的事件)):
- UserWebService.h
- #import
- //定义一个ws完成的delegate
- @protocol WsCompleteDelegate
- @required
- -(void) finished;//需要实现的方法
- @end
- @interface UserWebService:NSObject
- {
- id delegate;//一个id类型的dategate对象
- }
- @property (assign) id delegate;
- -(id)initWithUserData:(User *)user;
- -(void)connectionDidFinishLoading:(NSURLConnection *)connection;
- @end
- UserWebService.m:
- #import
- @systhesize delegate;//同步这个delegate对象
- @implementation UserWebService
- -(void)connectionDidFinishLoading:(NSURLConnection *)connection
- {
- [delegate finished]
- }
- @end
LoginViewController.h:
- #import "UserWebService.h" //包含含有委托的头文件
- @interface LoginViewController:UIViewController
- -(void)submit;
- @end
- LoginViewController.m:
- @implementation LoginViewController
- -(void) submit
- {
- User *user = [[User alloc]init];
- [user setUserId:@"username"];
- [user setPassword:@"password"];
- ws = [[UserWebService alloc] initWithUserData:user];
- ws.delegate = self;//设置委托的收听对象
- [user release];
- [ws send];
- }
- //实现委托中的方法,
- -(void) finished
- {
- NSAttry *users = [ws users];
- }
- @end
可以看到,delegate声明为assign:
- @property (assign) id delegate;
复制代码
如果声明为retain会如何?
- LoginViewController alloc了一个UserWebService,UserWebService的代理又是LoginViewController,这样就循环引用了:
- ws = [[UserWebService alloc] initWithUserData:user]; //UserWebService对象引用计数加1
- ws.delegate = self;//LoginViewController对象引用计数加1
外部框架allocLoginViewController对象后,LoginViewController对象的引用计数为2 ,release后还是无法销毁,产生内存泄漏
所以用assign而不是retain声明属性可以避免循环引用,ARC下用弱引用也可以解决
内存检测可以用xcode继承的instrument工具,不过循环引用引起的内存泄露是检测不出来的
对象release到引用计数为0后,如果对应指针没有赋值为nil,怎出现野指针
- ClassA *a = [[ClassA alloc] init];
a = nil;//alloc的内存没有任何对象可以控制它了,引用计数永远为1,这就造成了内存泄露
简单的赋值操作并不会改变对象的引用计数:
- ClassA *a = [[ClassA alloc] init];
- ClassA *b = a;//a和b指向的对象的引用计数还是1
@property:
默认为@property为@property(atomic,assign)
nonatomic: 没有对应的atomic关键字,即使上面是这么写,但atomic叧是在你没有声明这个特性的时候系统默认,你无法主动去声明这一特性。nonatomic不支持多线程访问,atomic有同步机制,支持多线程访问,如果需要多线程访问,声明为atomic(维持默认),否则声明为nonatomic,因为nonatomic效率比atomic高得多
关于assign、retain和copy: assign是系统默认的属性特性,它几乎适用亍OC的所有变量类型。对于非对象类型的变量,assign是唯一可选的特性。但是如果你在引用计数下给一个对象类型的变量声明为assign,那么你会在编译的时候收到一条来自编译器的警告。因为assign对于在引用计数下的对象特性,叧创建了一个弱引用(也就是平时说的浅复制)。返样使用变量会很危险。当你release了前一个对象的时候,被赋值的对象指针就成了无头指针了。因此在为对象类型的变量声明属性的时候,尽量少(或者不要)使用assign。
关于assign合成的setter,看起来是这样的:
- -(void)setObjA:(ClassA *)a {
- objA = a;
- }
在深入retain之前,先把声明为retain特性的setter写出来:
- -(void)setObjA:(ClassA *)a
- {
- If(objA != a)
- {
- [objA release];
- objA = a;
- [objA retain]; //对象的retain count 加1
- }
- }
明显的,在retain的setter中,变量retain了一次,那么,即使你在程序中 self.objA = a; 只写了这么一句,objA仍然需要release,才能保证对象的retain count 是正确的。但是如果你的代码 objA = a; 叧写了这么一句,那么这里只是进行了一次浅复制,对象的retain count 并没有增加,因此这样写的话,你不需要在后面release objA。 这2句话的区别是,第一句使用了编译器生成的setter来设置objA的值,而第二句叧是一个简单的指针赋值
- NSString *str = [[NSString alloc] initwithstring @“abc”];
- str = @“abcd”;‘
- [str release];
- NSLog("%@",str);//打印出abcd
str为什么没有变成野指针呢?因为字符串常量(包括NSString和@“......”)的引用计数很大(100K+),基本上不会释放掉(由OC自己管理),所以字符串常量可以不用release
转载于:https://www.cnblogs.com/DamonTang/p/3380193.html
iOS 循环引用 委托 (实例说明)相关推荐
- iOS循环引用问题集合、内存泄漏、僵尸对象、代码静态分析
内存泄漏:https://my.oschina.net/llfk/blog/1031291 内存泄漏监测自动化:http://www.cocoachina.com/articles/18490 fac ...
- iOS容易造成循环引用的三种场景,就在你我身边!
ARC已经出来很久了,自动释放内存的确很方便,但是并非绝对安全绝对不会产生内存泄露.导致iOS对象无法按预期释放的一个无形杀手是--循环引用.循环引用可以简单理解为A引用了B,而B又引用了A,双方都同 ...
- [iOS]ARC下循环引用的问题
转载自:http://blog.cnbang.net/tech/2085/ [iOS]ARC下循环引用的问题 2013-8-30 最初 最近在开发应用时碰到使用ASIHttpRequest后在某些机器 ...
- [iOS]-NSTimer与循环引用的理解
目录: 参考的博客: 问题引入 循环引用 简单的循环引用 Block中的循环引用强弱共舞 Delegate中的循环引用 NSTimer 创建NSTimer 销毁NSTimer invalidate f ...
- iOS: NSTimer的循环引用(解决)
首先有两个概念写在最前: 内存泄漏:系统分配的内存空间在使用完毕之后没有进行及时的回收,称之为发生了内存泄漏. 内存溢出:指在申请内存的时候,没有足够的内存空间可以使用,包括栈溢出和堆溢出. 下面开始 ...
- iOS开发笔记(二):block循环引用
写这篇文章的缘由是第一次面试时被问到了block循环引用的问题,当时回答的不是很好,首先要明确的是,block是否用copy修饰决定不了循环引用的产生,在此再一次进行补强,有不对的地方还请多多指教. ...
- ios开发 循环引用 检测_iOS开发——Block引起循环引用的解决方案
[目前总结了一下,在iOS平台容易引起循环引用的几个场景:一.parent-child模式二.block(编译器会提示警告)三.NSTimer] up vote 0 down vote favorit ...
- IOS小知识点5之内存警告、循环引用、交叉引用
IOS的内存使用有以下几个等级,最常见的就是OSMemoryNotificationLevelWarning OSMemoryNotificationLevelUrgent typedef enum ...
- ios Block底层详解、框架结构:捕获、对象类型、__block、__forwarding、循环引用
1:捕获 2:block类型 2.1:问题 :mrc环境下 下面讲的都是mrc环境下,会真实很多 2.2:在arc下,block 自动加上copy的情况---:返回block. 2.3:在arc下, ...
最新文章
- 婚纱摄影小程序能带来订单吗?小程序如何做营销?
- 数据传输流程和socket简单操作
- java数组去重_再谈JavaScript数组去重
- java.net.URISyntaxException: Illegal character in query
- RedisTemplate和StringRedisTemplate使用
- android 属性动画还原,属性动画和补间动画
- Inno Setup使用技巧
- linux虚拟arm环境环境,Ubuntu 模拟ARM开发环境
- 为什么越来越多的人都不喜欢用信用卡?
- java房屋出租系统
- 现有开发语言以及适用范围
- mysql 按照条件计数_Mysql按条件计数的几种方法
- 股票涨跌的心理学原理: 过度反应理论
- 自制PMW3901光流模块
- pollard_rho
- 二分类神经网络结果准确率50%,loss一直在0.69的解决方法
- sourceinsight 查看源码的利器
- 「Python数据分析系列」10.使用数据
- 我使用Feign上传文件踩的坑,MultipartFile文件死活传不过去
- Destoon7.0会员中心模板 B2B系统商务中心模板源码下载
热门文章
- 原python实现素数判断_Python实现求最大公约数及判断素数的方法
- 关于数据分析部门组织架构的探讨
- c语言运行程序没有,这个程序怎么运行?为什么显示没有exe??
- python自定义函数的关键字_python学习之--自定义函数:
- Android NDK开发之 NDK 局部 全局引用
- excel函数手册_一个函数高手的成长之路
- Synopsys MetaWare for Linux 安装与编译指南
- CSS3 3D切割轮播图
- Kickstarter 开源其 Android 和 iOS 应用
- 超酷的 mip-infinitescroll 无限滚动(无限下拉)