• 当控制器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是强引用问题的更多相关文章

  1. JVM中强引用,弱引用,软引用和幽灵引用的代码

    上代码: public class ReferenceTest { public static void main(String[] args) { //test1();//软引用 //test2() ...

  2. Java中的四种引用类型,强引用,软引用,弱引用,虚引用

    对于Java中的垃圾回收机制来说,对象是否被回收的标准在于该对象是否被引用.因此,引用也是JVM进行内存管理的一个重要概念. Java中对象的引用一般有以下4种类型: 1强引用  2软引用  3弱引用 ...

  3. Java四大引用详解:强引用、软引用、弱引用、虚引用

    面试官考察Java引用会问到强引用.弱引用.软引用.虚引用,具体有什么区别?本篇单独来详解 @mikechen Java引用 从JDK 1.2版本开始,对象的引用被划分为4种级别,从而使程序能更加灵活 ...

  4. IOS开发中NSRunloop跟NSTimer的问题

    在Windows时代,大家肯定对SendMessage,PostMessage,GetMessage有所了解,这些都是windows中的消息处理函数,那对应在ios中是什么呢,其实就是NSRunloo ...

  5. ios NSTimer的强引用问题

    在一个controller中,使用 NSURLSessionDataTask *dataTask = [[NSURLSession sharedSession] dataTaskWithRequest ...

  6. IOS开发中滑动页面时NSTimer停止的问题

    我们在做倒计时的时候,发现当你手指按着屏幕不放,拖动tableView滑动的时候,写在cell上得倒计时停止倒计时,松开继续倒计时.研究发现就是拖动tableView滑动时,NSTimer停止了. 这 ...

  7. iOS开发中如何创建多个target

    在开发iOS应用程序的过程中,经常需要根据不同的需求,切换到不同的项目配置,或者打不同的包(测试环境.开发环境.生产环境等等),如果每次都是手动配置,一则比较麻烦,二则容易配置错,那么有没有更好的方案 ...

  8. iOS开发中的零碎知识点笔记 韩俊强的博客

    每日更新关注:http://weibo.com/hanjunqiang  新浪微博 1.关联 objc_setAssociatedObject关联是指把两个对象相互关联起来,使得其中的一个对象作为另外 ...

  9. iOS开发系列-定时器强引用问题

    概述 iOS开发中常用的定时器NSTimer.CADisplayLink. NSTimer 和 CADisplayLink 基本使用 NSTimer的创建方法有两个scheduledTimerWith ...

随机推荐

  1. 【CentOS】ifconfig命令 :command not found & yum命令 :cannot find a valid baserl for repo: base/7/x86_64

    第一课,学习的是安装linux的远程连接.相信看阿铭视频的朋友们都会知道,第一个开机输入完root后要敲的命令就是--ifconfig 非常幸运,这迎来了我的第一个问题 这时候你会选择百度,会搜索到这 ...

  2. ContentControl与ContentPresenter区别?

    <TextBlock HorizontalAlignment="Left" Text="{Binding HwContent, Converter={StaticR ...

  3. Symmetric Tree

    Given a binary tree, check whether it is a mirror of itself (ie, symmetric around its center). For e ...

  4. C语言_第三章

    1.常量        1.整型常量        2.实型常量                1.十进制小数形式,由数字和小数点组成.                2.指数形式(以E或e代表以10 ...

  5. hibernate 的SessionFactory的getCurrentSession 与 openSession() 的区别

    1 getCurrentSession创建的session会和绑定到当前线程,而openSession不会. 2 getCurrentSession创建的线程会在事务回滚或事物提交后自动关闭,而ope ...

  6. Django 基本命令

    1. 新建一个 django project django-admin.py startproject project-name 一个 project 为一个项目,project-name 项目名称, ...

  7. MongoDB 3.X 用户权限控制

    摘要: MongoDB 3.0 安全权限访问控制,在添加用户上面3.0版本和之前的版本有很大的区别,这里就说明下3.0的添加用户的方法. 环境.测试: 在安装MongoDB之后,先关闭auth认证,进 ...

  8. html5新特性

    这一篇博文不会告诉你怎么去使用html5的新特性,只会给你总结一下新特性------对于好学的人可以把这篇文章当做一个目录 对于初接触的人来说是一个导向 对于已经接触过的人来说是一个检测你掌握程度的检 ...

  9. hdu 4898 The Revenge of the Princess’ Knight

    传送阵:http://acm.hdu.edu.cn/showproblem.php?pid=4898 题目大意:一个首尾相连的字符串,将其分为k个子串,使得最大的字串最小 将所有子串排序,输出第k小即 ...

  10. 自动爬取ZiMuZu的内容发布到Wordpress

    先说一下大致的步骤. 首先需要模拟浏览器登录网站才能看到相应电影信息, 然后通过正则表达式从网页源代码中筛选出所需要的电影, 最后通过python-wordpress-xmlrpc将信息逐条发布到Wo ...