您的位置:首页 > 移动开发 > Swift

Swift中Timer计时器循环引用问题

2017-08-22 11:58 946 查看
老问题,和OC写法差不多。用计时器发现deinit方法不走,页面有内存泄漏,而且计时器关不掉。

deinit {
// 销毁计时器
timer?.invalidate();
}可以在特定节点主动调用
timer?.invalidate();
但是并不完美~~
简单说下问题点:self对自己的计时器属性timer强引用,timer设置target:self,并且是循环操作计时器(repeats:true),timer对self也是强引用,循环引用了。deinit就不执行。

方案:timer扩展方法,将要执行的操作,就是selector(...),以block的形式传入userinfo中,以此打破循环。

//
// Timer+Extensions.swift
// MPPForSwift
//
// Created by meipaipai on 2017/8/22.
// Copyright © 2017年 liyinkai. All rights reserved.
//

import Foundation

extension Timer {

class func lyk_scheduledTimer (timeInterval: TimeInterval, repeats: Bool, completion:((_ timer:Timer)->())) -> Timer{
return Timer.scheduledTimer(timeInterval: timeInterval, target: self, selector: #selector(lyk_completionLoop(timer:)),
userInfo: completion, repeats: repeats);
}

@objc class func lyk_completionLoop(timer:Timer) {
guard let completion = timer.userInfo as? ((Timer) -> ()) else {
return;
}
completion(timer);
}

}以上代码是给timer扩展两个类方法
// MARK: - 计时器相关方法
extension LYKVerificationCodeViewController {
/// 创建计时器
fileprivate func setupTimer () {
timer = Timer.lyk_scheduledTimer(timeInterval: 1.0, repeats: true, completion: { [weak self](timer) in
guard let strongSelf = self else {
return;
}
strongSelf.timerFunc();
});
}

/// 计时器实现方法
fileprivate func timerFunc () {
sixtySecond = sixtySecond - 1;
print(sixtySecond);
countDownLabel.text = "接收短信大概需要\(sixtySecond)秒钟";
if sixtySecond == 0 {
// 暂时计时器,重置 60 秒计时时间
timer?.fireDate = Date.distantFuture;
sixtySecond = 60;
// 显示重新发送按钮
countDownLabel.isHidden = true;
resendButton.isHidden = false;
}
}
}以上代码是操作计时器代码。基本和OC的逻辑差不多。
值得一说的点,[weak self],相当于OC的__weak。写了这个,block中所有的self都是弱引用了(是比OC方便点。。。)。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: