Xamarin iOS:如何实现可跨两个ViewController管控的Timer(解决无法停止问题)
解决SecondViewController返回后Timer无法停止的问题
这是iOS(Xamarin.iOS)开发里非常常见的坑,我来给你拆解问题和解决方案:
问题根源
当你从SecondViewController返回时,虽然界面被移除,但如果Timer没有被主动停止并置空,它会继续运行——而且Timer默认会强引用它的目标对象(也就是你的secondViewController实例),导致VC无法被GC回收,同时你也失去了对这个Timer的引用,自然没法再控制它停止。
具体解决方案
1. 把Timer存为实例变量,利用VC生命周期停止它
首先,你需要把Timer定义成secondViewController的私有成员变量(不能是局部变量,不然你没法在其他方法里拿到它),然后在视图即将消失的生命周期方法里停止并销毁它:
private Timer _timer; // 类级别的成员变量 public secondViewController(IntPtr handle) : base(handle) { } // 假设你在ViewDidLoad或者ViewWillAppear里创建Timer public override void ViewWillAppear(bool animated) { base.ViewWillAppear(animated); // 先检查是否已有Timer在运行,避免重复创建 _timer?.Invalidate(); _timer = Timer.CreateScheduledTimer(timeintervalle, () => { // 这里写你的Timer逻辑,比如更新UI、计算数值等 UpdateTimerTask(); }); } public override void ViewWillDisappear(bool animated) { base.ViewWillDisappear(animated); // 停止Timer并置空,打破循环引用 _timer?.Invalidate(); _timer = null; } private void UpdateTimerTask() { // 你的Timer具体执行逻辑,比如更新Vconcentration、Vpoids这些变量 }
2. 避免循环引用(关键)
如果你的Timer回调用了lambda表达式,一定要注意避免循环引用。可以用弱引用包裹当前VC实例,防止Timer强持有VC导致内存泄漏:
public override void ViewWillAppear(bool animated) { base.ViewWillAppear(animated); _timer?.Invalidate(); var weakSelf = new WeakReference<secondViewController>(this); _timer = Timer.CreateScheduledTimer(timeintervalle, () => { if (weakSelf.TryGetTarget(out var self)) { // 只有VC还存在时才执行逻辑 self.UpdateTimerTask(); } else { // VC已被回收,主动停止Timer _timer?.Invalidate(); _timer = null; } }); }
3. 不要用外部强引用控制Timer
别想着在第一个ViewController里持有secondViewController的强引用来控制Timer,这种做法很容易导致内存泄漏,最好的实践是让每个VC自己管理自己的Timer,利用生命周期方法完成创建和销毁。
额外注意点
- 每次进入视图时先检查Timer状态,避免重复创建多个Timer同时运行;
- 如果Timer涉及UI更新,一定要确保在主线程执行(Xamarin.iOS里可以用
InvokeOnMainThread); - 如果你的Timer是重复执行的,记得用
Timer.CreateRepeatingTimer而不是单次的CreateScheduledTimer(根据你的需求选择)。
内容的提问来源于stack exchange,提问作者QuenPley
相关产品推荐
相关产品推荐

