今天,我正在阅读快速编程指南here的“封闭的强大参考周期”,而我的问题就是基于此。
我在导航控制器中嵌入了两个视图控制器,在第一个视图控制器中什么也没有,仅用于连接到secondviewcontroller,并且在secondViewcontroller中也有以下代码,也称为ViewController2。
代码1:
class ViewController2: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true) { (_) in
print("timer")
}
}
}
弹出到第一个视图控制器后,该计时器将不会结束,它将连续打印“计时器”。如何停止呢?,下面是Debug内存图的屏幕截图。
如上图所示,我们可以看到没有第二个视图控制器的实例,但是计时器将连续执行!
如果我在定时器关闭时持有或使用自己的强烈推荐,那么我相信这是可以的。但是按照上面的代码,我没有持有或使用任何强引用,并且它也显示在Debug内存图中(弹出后没有secondviewcontroller的引用)。
如果我使用下面的代码,那么我接受计时器正在运行,因为按照下面的代码,它具有较强的引用周期。
代码2:
class ViewController2: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true) { (_) in
print("\(self.view.tag)")
}
}
}
下面是调试内存图,弹出到第一个视图控制器后可以看到,第二个视图控制器ref仍然是。
根据我的代码2部分,我可以接受它正在运行,因为viewcontroller2仍在内存中并且正在运行。但是在我的代码1部分中,内存中没有viewcontrller2的迹象,并且它的计时器有效吗?为什么呢? 如何在不将其设置为实例的情况下停止此操作。
最佳答案
您可以在SecondVC弹出之前停止计时器
您需要实例变量
var timer : Timer;
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
if timer != nil && self.isMovingFromParentViewController {
timer.invalidate()
timer = nil
}
}
编辑:
好的,我接受,但是为什么xcode不在内存图中显示它。如
没有viewcontroller2的实例。
所以基本上你的问题是你想知道为什么你的第一个代码中没有ViewController2引用,以及为什么当你在内存图中使用第二个代码时有一个ViewController2引用:)
什么是块?
为了理解它,您必须了解块/闭合的概念。
块/关闭不过是堆内存中引用计数的对象(如结构)而已。
当您将块作为参数传递时,会将对象在堆中从一个函数传递到另一个函数。
这些是引用计数的对象,因此ARC的所有规则也适用于它们。
上下文捕获
闭包与它的其他当代部分(实例和静态方法)不同的唯一原因是ContextCapturing。块能够捕获在其上下文之外声明的变量,而实例和静态方法则不能。
什么是上下文捕获?
每次编译器看到Closure / Block的语法时,它都会将Closure中的所有代码复制到堆中的对象。与此同时,它复制了在其中访问的所有变量。这就是闭包能够访问超出其作用域声明的变量的原因。
您为什么要告诉我这一切?
在你的代码中
Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true) { (_) in
print("\(self.view.tag)")
}
当您在闭包内部访问self时,您的Second VC将被复制到堆内存中的闭包对象。因为第二VC的强大参考引用计数增加了+1。
因此,当您单击后退按钮时,不会释放第二个VC,因为ARC仅在其引用计数为0时才删除对象。
在您的代码中
Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true) { (_) in
print("timer")
}
U尚未访问self,因此当SecondVC引用计数从未更改为其原始值时。因此,当您点击后退按钮时,将在第二个VC上调用
这就是为什么您在第一代码中看不到第二个VC的引用的原因。
为什么您会看到Sweeper在他的回答中已经解释了Timer的延迟:)没有必要再次解释
关于ios - 如何停止类(class)计时器? - swift ,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/46048628/