ios - NSTimer中target的self是强引用问题
当控制器ViewController跳转进入控制器OneViewController中的时候开启定时器,让定时器每隔一段时间打印一次,当OneViewController dismiss的时候,控制器并没有被销毁.然而定时器的timer invalidate 在dealloc中已经写了.
如果没有定时器,则OneViewController可以正常销毁.
原因在于下图:循环引用

控制器ViewController跳转进入OneViewController中开启定时器
#import "OneViewController.h"
@interface OneViewController ()
@property (nonatomic, strong) NSTimer *timer;
@end
@implementation OneViewController
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
[self dismissViewControllerAnimated:YES completion:nil];
}
-(void)viewDidLoad{
[super viewDidLoad];
self.view.backgroundColor = [UIColor orangeColor];
/**
1.__weak typeof(self) weakSelf = self; 不能解决
*/
//开启定时器
self.timer = [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(testTimerDeallo) userInfo:nil repeats:YES];
}
/** 方法一直执行 */
-(void)testTimerDeallo{
NSLog(@"-----");
}
- 当开启定时器以后,testTimerDeallo方法一直执行,即使dismiss此控制器以后,也是一直在打印,而且dealloc方法不会执行.循环引用造成了内存泄露,控制器不会被释放.
/** 开启定时器以后控制器不能被销毁,此方法不会被调用 */
-(void)dealloc{
NSLog(@"xiaohui");
[self.timer invalidate];
}
@end
- 解决办法: 由于循环引用的起因是target,则可以包装一个target,让target是另一个对象,而不是ViewController即可.
- 1.创建一个集成NSObject的分类TimerWeakTarget,创建类方法---开启定时器的方法
#import <Foundation/Foundation.h>
@interface TimerWeakTarget : NSObject
@property (nonatomic, assign) SEL selector;
@property (nonatomic, weak) NSTimer *timer;
@property (nonatomic, weak) id target;
/**
1.重写开启定时器方法,在内部对target进行替换,换成本类(TimerWeakTarget)的对象即可
2.不会造成循环引用了,原控制器OneViewController属性有timer对timer强应用,timer内部对self强引用,但是self在此方法内部被替换成了本类的对象(TimerWeakTarget *),而本类的对象不会对OneViewController强引用,则不会造成循环引用,也就不会造成内存泄露
*/
+ (NSTimer *) scheduledTimerWithTimeInterval:(NSTimeInterval)interval
target:(id)aTarget
selector:(SEL)aSelector
userInfo:(id)userInfo
repeats:(BOOL)repeats;
@end
- TimerWeakTarget.m文件中
- 在下面我们封装的类的方法中,我们将开启定时器的方法 [NSTimer scheduledTimerWithTimeInterval:interval target:timer selector:@selector(fire:) userInfo:userInfo repeats:repeats];中的target换掉了,换成了 本类的对象,timer.在OneViewController中开启定时器的时候直接调用这个类方法,就不会造成循环引用.看图

#import "TimerWeakTarget.h"
@implementation TimerWeakTarget
+ (NSTimer *) scheduledTimerWithTimeInterval:(NSTimeInterval)interval
target:(id)aTarget
selector:(SEL)aSelector
userInfo:(id)userInfo
repeats:(BOOL)repeats{
TimerWeakTarget * timer = [TimerWeakTarget new];
timer.target = aTarget;
timer.selector = aSelector;
//-------------------------------------------------------------此处的target已经被换掉了不是原来的VIewController而是TimerWeakTarget类的对象timer
timer.timer = [NSTimer scheduledTimerWithTimeInterval:interval target:timer selector:@selector(fire:) userInfo:userInfo repeats:repeats];
return timer.timer;
}
-(void)fire:(NSTimer *)timer{
if (self.target) {
[self.target performSelector:self.selector withObject:timer.userInfo];
} else {
[self.timer invalidate];
}
}
@end
- 控制器dismiss以后可以正常被销毁.问题解决.
ios - NSTimer中target的self是强引用问题的更多相关文章
- JVM中强引用,弱引用,软引用和幽灵引用的代码
上代码: public class ReferenceTest { public static void main(String[] args) { //test1();//软引用 //test2() ...
- Java中的四种引用类型,强引用,软引用,弱引用,虚引用
对于Java中的垃圾回收机制来说,对象是否被回收的标准在于该对象是否被引用.因此,引用也是JVM进行内存管理的一个重要概念. Java中对象的引用一般有以下4种类型: 1强引用 2软引用 3弱引用 ...
- Java四大引用详解:强引用、软引用、弱引用、虚引用
面试官考察Java引用会问到强引用.弱引用.软引用.虚引用,具体有什么区别?本篇单独来详解 @mikechen Java引用 从JDK 1.2版本开始,对象的引用被划分为4种级别,从而使程序能更加灵活 ...
- IOS开发中NSRunloop跟NSTimer的问题
在Windows时代,大家肯定对SendMessage,PostMessage,GetMessage有所了解,这些都是windows中的消息处理函数,那对应在ios中是什么呢,其实就是NSRunloo ...
- ios NSTimer的强引用问题
在一个controller中,使用 NSURLSessionDataTask *dataTask = [[NSURLSession sharedSession] dataTaskWithRequest ...
- IOS开发中滑动页面时NSTimer停止的问题
我们在做倒计时的时候,发现当你手指按着屏幕不放,拖动tableView滑动的时候,写在cell上得倒计时停止倒计时,松开继续倒计时.研究发现就是拖动tableView滑动时,NSTimer停止了. 这 ...
- iOS开发中如何创建多个target
在开发iOS应用程序的过程中,经常需要根据不同的需求,切换到不同的项目配置,或者打不同的包(测试环境.开发环境.生产环境等等),如果每次都是手动配置,一则比较麻烦,二则容易配置错,那么有没有更好的方案 ...
- iOS开发中的零碎知识点笔记 韩俊强的博客
每日更新关注:http://weibo.com/hanjunqiang 新浪微博 1.关联 objc_setAssociatedObject关联是指把两个对象相互关联起来,使得其中的一个对象作为另外 ...
- iOS开发系列-定时器强引用问题
概述 iOS开发中常用的定时器NSTimer.CADisplayLink. NSTimer 和 CADisplayLink 基本使用 NSTimer的创建方法有两个scheduledTimerWith ...
随机推荐
- [转]js 将图片连接转换称base64格式
参考:http://blog.csdn.net/wyyfwm/article/details/45917255 我们把图像文件的内容直接写在了HTML 文件中,这样做的好处是,节省了一个HTTP 请求 ...
- Guava学习笔记(3):复写的Object常用方法
转自:http://www.cnblogs.com/peida/p/Guava_Objects.html 在Java中Object类是所有类的父类,其中有几个需要override的方法比如equals ...
- uboot的编译
在我拿到开发板以后,uboot都是编译好的,但是我不知道它是如何生成uboot.bin文件的.经过一番摸索.我也会编译uboot了. #cd /home #mkdir study //创建工作目录 * ...
- 打造自己的php动态连接库文件
http://blog.163.com/weibin_li/blog/static/1901464172012325115517181/
- CentOS 6.5 下 CDH 5.2.1 集群安装(一)
集群节点数量3 个 192.168.1.170 cdh-master 192.168.1.171 cdh-slave-1 192.168.1.171 cdh-slave-2 一.安装CentOS6.5 ...
- LightOJ1126 Building Twin Towers(DP)
题目 Source http://www.lightoj.com/volume_showproblem.php?problem=1126 Description Professor Sofdor Al ...
- CodeForces 548
A. Mike and Fax time limit per test 1 second memory limit per test 256 megabytes input standard inpu ...
- Python for Informatics 第11章 正则表达式五(译)
注:文章原文为Dr. Charles Severance 的 <Python for Informatics>.文中代码用3.4版改写,并在本机测试通过. 11.4 转义字符 之前我们在正 ...
- Excel大批量导入数据到SQLServer数据库-万条只用1秒
private string ExcelToStudent() { /*---*/ var preStr = DateTime.Now.ToString("yyyyMMddHHmmssfff ...
- C# WinForm 慎用 override CreateParams 来重载窗体的一些特性
窗体和控件的属性CreateParams(这真的是一个属性)很神奇,因为通过它你能够很方便的控制窗体或控件诸如边框.最大化最小化关闭按钮的隐藏.窗体的模式化弹窗模式等的一些特性.虽然,CreatePa ...