iOS循环引用的三种场景
来源:互联网 发布:dota2第一滴血数据bug 编辑:程序博客网 时间:2024/05/24 01:35
(1)计时器NSTimer
- 若timer一直处于validate的状态,则其引用计数将始终大于0。
- NSTimer经常会被作为某个类的成员变量,而NSTimer初始化时要指定self为target,容易造成循环引用。
先看一段NSTimer使用的例子(ARC模式):
#import <Foundation/Foundation.h> @interface Friend : NSObject - (void)cleanTimer; @end #import "Friend.h" @interface Friend () { NSTimer *_timer; } @end @implementation Friend - (id)init { if (self = [super init]) { _timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(handleTimer:) userInfo:nil repeats:YES]; } return self; } - (void)handleTimer:(id)sender { NSLog(@"%@ say: Hi!", [self class]); } - (void)cleanTimer { [_timer invalidate]; _timer = nil; } - (void)dealloc { [self cleanTimer]; NSLog(@"[Friend class] is dealloced"); }
在类外部初始化一个Friend对象,并延迟5秒后将friend释放(外部运行在非arc环境下)
Friend *f = [[Friend alloc] init]; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, *NSEC_PER_SEC), dispatch_get_main_queue(), ^{ [f release]; });
我们所期待的结果是,初始化5秒后,f对象被release,f的dealloc方法被调用,在dealloc里面timer失效,对象被析构。但结果却是如此:
2015-03-18 18:00:35.300 WZLCodeLibrary[41422:3390529] Friend say: Hi!2015-03-18 18:00:36.299 WZLCodeLibrary[41422:3390529] Friend say: Hi!2015-03-18 18:00:37.300 WZLCodeLibrary[41422:3390529] Friend say: Hi!2015-03-18 18:00:38.299 WZLCodeLibrary[41422:3390529] Friend say: Hi!2015-03-18 18:00:39.299 WZLCodeLibrary[41422:3390529] Friend say: Hi!//运行了5次后没按照预想的停下来2015-03-18 18:00:40.299 WZLCodeLibrary[41422:3390529] Friend say: Hi!2015-03-18 18:00:41.300 WZLCodeLibrary[41422:3390529] Friend say: Hi!2015-03-18 18:00:42.300 WZLCodeLibrary[41422:3390529] Friend say: Hi!2015-03-18 18:00:43.299 WZLCodeLibrary[41422:3390529] Friend say: Hi!2015-03-18 18:00:44.300 WZLCodeLibrary[41422:3390529] Friend say: Hi!<br>.......根本停不下来.....
这是为什么呢?
- timer持有Friend对象,而此时timer不停止计时就不会释放,它继续持有Friend对象,Friend对象就不会进入dealloc;
一个比较好的解决方法是开放这个函数,让Friend的调用者显式地调用来清理现场。如下:
Friend *f = [[Friend alloc] init];dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 5*NSEC_PER_SEC), dispatch_get_main_queue(), ^{ [f cleanTimer]; [f release];});
(2)block
block在copy时都会对block内部用到的对象进行强引用(ARC)或者retainCount增1(非ARC)。在ARC与非ARC环境下对block使用不当都会引起循环引用问题,一般表现为:
- 某个类将block作为自己的属性变量,然后该类在block的方法体里面又使用了该类本身.
#import "Friend.h"@interface Friend ()@property (nonatomic) NSArray *arr;@end@implementation Friend- (id)init{ if (self = [super init]) { self.arr = @[@111, @222, @333]; self.block = ^(NSString *name){ NSLog(@"arr:%@", self.arr); NSLog(@"arr:%@", _arr); }; } return self;}
解决方法:
__weak typeof(self) weakSelf = self;self.blkA = ^{//加一下强引用,避免weakSelf被释放掉__strong typeof(weakSelf) strongSelf = weakSelf;//不会导致循环引用.NSLog(@"%@", strongSelf->_xxView); };
(3)委托delegate
声明delegate时手贱玩用了retain或者strong。
解决方法:
- 声明delegate时请用assign(MRC)或者weak(ARC)
【原文】iOS容易造成循环引用的三种场景,就在你我身边!
0 0
- iOS循环引用的三种场景
- iOS 容易引“起循环引用”的三种场景
- iOS容易造成循环引用的三种场景
- iOS容易造成循环引用的三种场景
- iOS中容易造成循环引用的三种场景
- 【转】iOS容易造成循环引用的三种场景
- iOS容易造成循环引用的三种场景
- iOS容易造成循环引用的三种场景
- iOS容易造成循环引用的三种场景,(循环引用),内存泄漏
- ios 循环引用的场景
- iOS容易造成循环引用的三种场景之Block以及对应的使用方法(二)
- iOS容易造成循环引用的三种场景NSTimer以及对应的使用方法(一)
- iOS容易造成循环引用的三种场景,就在你我身边!
- iOS容易造成循环引用的三种场景,就在你我身边!
- iOS容易造成循环引用的三种场景,就在你我身边!
- iOS容易造成循环引用的三种场景及其解决
- [转]iOS容易造成循环引用的三种场景,就在你我身边!
- iOS容易造成循环引用的三种场景,就在你我身边!
- 用Gradle构建时,将密码等敏感信息放在build.gradle之外
- Bulls and Cows
- 学生信息管理系统.servlet
- 《TCP/IP详解》学习笔记-第6/7/8章 ICMP/Ping/Traceroute
- Android 国际化
- iOS循环引用的三种场景
- iOS开发之处理网络图片的步骤
- c语言字符串
- 30分钟LINQ教程
- 【转】IOS NSTimer 定时器用法总结
- Producer consumer model
- 如何修改eclipse中@author的默认选项
- Android地图尝试之两行代码调用高德地图来完成位置展示
- Pycharm2016.1.2注册码(python编码利器)