如何为多个不同的控制器制作 NSTimer?迅速

Posted

技术标签:

【中文标题】如何为多个不同的控制器制作 NSTimer?迅速【英文标题】:How to make NSTimer for multiple different controllers? In swift 【发布时间】:2015-12-21 14:12:05 【问题描述】:

我在 page-based.based 上制作应用程序。我有多个不同的控制器。每个控制器都有NSTimer,它在控制器viewDidAppear() 时打开。当控制器为viewDidDisappear() 时,我关闭了 NSTimer。当我在控制器之间缓慢滑动时它可以工作,但如果我快速滑动控制器,一些计时器不会关闭。我尝试了几种不同的方法。第一种方法是我将通知发布到关闭计时器的功能,但当我在控制器之间缓慢滑动时它也可以工作。第二种方法我创建了公共类计时器,我将它用于每个控制器,但它对我不起作用。我不知道我该怎么做。请帮我。我在 UIView 中也有 NSTimer,它位于 UIViewController 上,当 UIViewController 消失时我需要它来关闭两个计时器。我怎样才能做到?

我在ViewController上的例子

  var timer: NSTimer!
  override func viewDidAppear(animated: Bool) 
        super.viewDidAppear(true)
        notificationCenter.postNotificationName("turnOnMemoryArc", object: nil)
        timer = NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: "showMemory", userInfo: nil, repeats: true)
    

    override func viewDidDisappear(animated: Bool) 
        super.viewDidDisappear(true)
        if timer != nil 
            timer.invalidate()
        
        notificationCenter.postNotificationName("turnOffMemoryArc", object: nil)
    

视图中的这段代码

  override func drawRect(rect: CGRect) 
        notificationCenter.addObserver(self, selector: "turnOnMemoryTimer", name: "turnOnMemoryArc", object: nil)
        notificationCenter.addObserver(self, selector: "turnOffMemoryTimer", name: "turnOffMemoryArc", object: nil)
//        timer = NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: "drawMemoryArc", userInfo: nil, repeats: true)
    

  func turnOnMemoryTimer() 
        print("memory timer is on")
        timer = NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: "drawMemoryArc", userInfo: nil, repeats: true)
    

    func turnOffMemoryTimer() 
        if timer != nil 
            timer.invalidate()
        
        print("Memory timer turned")
    

第二种方法

import Foundation

public class GlobalTimer 

    public init()  
    public var controllerTimer: NSTimer!
    public var viewTimer: NSTimer!


视图控制器

 override func viewDidAppear(animated: Bool) 
    super.viewDidAppear(true)
    notificationCenter.postNotificationName("turnOnBatteryArc", object: nil)
    if GlobalTimer().controllerTimer != nil 
        GlobalTimer().controllerTimer.invalidate()
        GlobalTimer().controllerTimer = NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: "batteryStateForLabel", userInfo: nil, repeats: true)
     else 
        GlobalTimer().controllerTimer = NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: "batteryStateForLabel", userInfo: nil, repeats: true)
    

界面视图

 func turnOnBatteryTimer() 
        print("turnOnBatteryTimer arc")
        if GlobalTimer().viewTimer != nil 
            GlobalTimer().viewTimer.invalidate()
            GlobalTimer().viewTimer = NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: "drawBatteryArc", userInfo: nil, repeats: true)
         else 
            GlobalTimer().viewTimer = NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: "drawBatteryArc", userInfo: nil, repeats: true)
        
    

【问题讨论】:

【参考方案1】:

您的代码中的主要问题是GlobalTimer()。这会在您每次编写 GlobalTimer() 时创建新的 GlobalTimer 实例。

以下代码中有四个不同实例 - 没有共享状态。

if GlobalTimer().viewTimer != nil 
    GlobalTimer().viewTimer.invalidate()
    GlobalTimer().viewTimer = NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: "drawBatteryArc", userInfo: nil, repeats: true)
 else 
    GlobalTimer().viewTimer = NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: "drawBatteryArc", userInfo: nil, repeats: true)

你可以用单例模式修复它...

public class GlobalTimer 
    public static let sharedInstance = GlobalTimer()
    private init()  
    public var controllerTimer: NSTimer!
    public var viewTimer: NSTimer!

...通过替换所有出现的GlobalTimer() ...

if GlobalTimer().viewTimer != nil 

...与GlobalTimer.sharedInstace ...

if GlobalTimer.sharedInstance.viewTimer != nil 

下一步是删除!,这很危险,如果您不知道自己在做什么,可能会导致崩溃。

public class GlobalTimer 
    public static let sharedInstance = GlobalTimer()
    private init()                       <-- avoid instantiation outside the file
    public var controllerTimer: NSTimer?   <-- was !
    public var viewTimer: NSTimer?         <-- was !

剩下的步骤是使用 GlobalTimer 替换您的代码 ...

if GlobalTimer().viewTimer != nil 
    GlobalTimer().viewTimer.invalidate()
    GlobalTimer().viewTimer = NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: "drawBatteryArc", userInfo: nil, repeats: true)
 else 
    GlobalTimer().viewTimer = NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: "drawBatteryArc", userInfo: nil, repeats: true)

...与...

GlobalTimer.sharedInstance.viewTimer?.invalidate()
GlobalTimer.sharedInstance.viewTimer = NSTimer.scheduled...

第一行说 - 如果 viewTimer != nil 则在 viewTimer 上调用 invalidate() 函数,否则什么也不会发生(类似于 ObjC 中的 nil 消息传递,...)。这允许您删除 if 条件,因为它使计时器无效或什么都不做。

第二行只是分配新的计时器。

【讨论】:

【参考方案2】:

尝试将 timer.invalidate() 放在视图中会消失而不是确实消失。执行此操作时,您根本不需要通知。

【讨论】:

以上是关于如何为多个不同的控制器制作 NSTimer?迅速的主要内容,如果未能解决你的问题,请参考以下文章

如何为iOS设备制作录屏指导视频

如何为控制多个散景图形添加一个图例?

如何为多个活动注册制作网站? [关闭]

如何为 FrameLayout 中的多个视图制作浮动上下文菜单?

如何为不同类型的用户制作出价表结构

UNITY - 如何为长按和单击/双击执行不同的操作?