1. NSTimer的使用

常见使用场景如下

- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor whiteColor];
    
    self.timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(timerAction) userInfo:nil repeats:YES];
    [[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];
    
}
- (void)timerAction{

     NSLog(@"打印了");
}

- (void)dealloc {

    [self.timer invalidate];
    self.timer = nil;

     NSLog(@"** dealloc **");
}

 但是在页面销毁时候,并没有dealloc方法定时器还在运行,这就造成内存泄漏了。

原因:由于NSTimer引用self,而 self又持有NSTimer对象,所以形成循环引用dealloc 永远不会被执行timer 也永远不会被释放,造成内存泄漏

常见解决方法

1.中间对象解决循环引用

中间对象代码如下

@interface TimerWeakObject : NSObject

+ (instancetype)proxyWithTarget:(id)target;

@end

@interface TimerWeakObject ()

@property (nonatomic ,weak)id target;

@end

@implementation TimerWeakObject

+ (instancetype)proxyWithTarget:(id)target {
    //NSProxy实例方法alloc
    TimerWeakObject *proxy = [TimerWeakObject alloc];
    proxy.target = target;
    return proxy;
}
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector{
    return [self.target methodSignatureForSelector:aSelector];

}
- (void)forwardInvocation:(NSInvocation *)anInvocation{
    [anInvocation invokeWithTarget:self.target];
}

@end

 界面调用代码如下

- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor whiteColor];
    
    self.timer = [NSTimer scheduledTimerWithTimeInterval:1 target:[TimerWeakObject proxyWithTarget:self] selector:@selector(timerAction) userInfo:nil repeats:YES];

    [[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];
    
}
- (void)timerAction{

     NSLog(@"打印了");
}

- (void)dealloc {

    [self.timer invalidate];
    self.timer = nil;

     NSLog(@"** dealloc **");
}

效果非常的明显,dealloc也走了,说明对象释放了,没有引用了。 

2.系统api方法解决循环引用 

在iOS 10以后系统,苹果针对NSTimer进行了优化,使用Block回调方式解决循环引用问题

self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0 repeats:YES block:^(NSTimer * _Nonnull timer) {
		 NSLog(@"打印了");
    }];
- (void)dealloc {

	[self.timer invalidate];
	self.timer = nil;

	 NSLog(@"** dealloc **");
}

使用这种系统的 api方法,会执行dealloc,只要在dealloc里面进行相关取消定时器操作就就可以了。

原文地址:https://blog.csdn.net/qq_35508084/article/details/128582630

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任

如若转载,请注明出处:http://www.7code.cn/show_32080.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注