2017-01-30 6 views
3

У меня есть таймер, который я запускаю в своем приложении, он использует функцию сохранения и перезагрузки, когда пользователь покидает представление и возвращается в представление. Однако, если я перехожу на другую вкладку в своем приложении, действия, необходимые для этой вкладки, по-видимому, прерывают таймер.Некоторые действия приложения Breaking TImer?

Будет ли это связано с использованием потоков в приложении и сопутствующими другими вкладками, нарушающими подсчет таймеров? Вот мой код таймера

Update 2: Вот мой пересмотренный код таймера в ...

// MARK: - SETTING UP SETS & TIMERS 

    func createStopTimeForRestFromUserTime(userTime: Int) -> Date { 
     let calendar = Calendar.current 
     let stopDate = calendar.date(byAdding: .second, value: userTime, to: Date()) 
     return stopDate! 
    } 

    func createTimer(stopDate: Date) { 
     print("CONSTRUCTING A TIMER") 
     userDefaults.set(stopDate, forKey: "setStopDate") 
     restTimer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(RestController.updateRestTimer), userInfo: nil, repeats: true) 
    } 

    func updateRestTimer() { 
     let presentTime = Date() 
     let stoppedTime = UserDefaults.standard.object(forKey: "setStopDate") as? Date 

     if stoppedTime?.compare(presentTime) == ComparisonResult.orderedDescending { 
       restRemainingCountdownLabel.text = dateComponentsFormatter.string(from: presentTime, to: stoppedTime!) 
      } else { 
       self.stopTimer() 
       print("THE TIMER IS NOW FINISHED") 
      } 
     } 

    func stopTimer() { 
     self.restTimer.invalidate() 
    } 

    // MARK: - CONFIGURE TIMER ON OPEN/CLOSE 

    override func viewWillDisappear(_ animated: Bool) { 
     print("VIEWWILLDISAPPEAR WAS CALLED") 
     stopTimer() 
     NotificationCenter.default.post(name: NSNotification.Name(rawValue: "ViewDidChangeNotification"), object: NSDate()) 
    } 

    func handleResumedTime(disappTime: NSDate) { 
     let disappearedTime = disappTime 
     let resumeTime = NSDate() 

     if disappearedTime.compare(resumeTime as Date) == ComparisonResult.orderedDescending { 
      print("RESUMING THE TIMER") 
      self.createTimer(stopDate: disappearedTime as Date) 
     } else { 
      print("TIMER HAS FINISHED") 
      stopTimer() 
     } 
    } 

    func handleTimerCallback(notification: NSNotification) { 
     if let date = notification.object as? NSDate { 
      self.handleResumedTime(disappTime: date) 
     } 
    } 

код в альтернативном коммутаторе VC ид, между которыми вызывает повреждение:

override func viewDidLoad() { 
    NotificationCenter.default.addObserver(self, selector: #selector(RoutineController.handleTimerCallback(notification:)), name: NSNotification.Name(rawValue: "ViewDidChangeNotification"), object: nil) 
} 

override func viewWillDisappear(_ animated: Bool) { 
    NotificationCenter.default.post(name: NSNotification.Name(rawValue: "ViewDidChangeNotification"), object: NSDate()) 
} 

func handleTimerCallback(notification: NSNotification) { 
    let date = notification.object 
    print("Object is \(date)") 
} 

EDIT: добавлена ​​обновленная функция управления ручками и консолью при изменении вкладок и изменении обратно ...

func handleResumedTime(disappTime: NSDate) { 
    let disappearedTime = disappTime as Date 
    let resumeTime = NSDate() as Date 
    print("ATTEMPTING RESUME") 
    print(disappearedTime) 
    print(resumeTime) 

    if resumeTime.compare(disappearedTime) == ComparisonResult.orderedAscending { 
     print("RESUMING THE TIMER") 
     self.createTimer(stopDate: disappearedTime) 
    } else { 
     print("TIMER HAS FINISHED") 
     stopTimer() 
    } 
} 

enter image description here

ответ

0

Попытайтесь сравнить таймеры в миллисекундах с помощью DateFormatter и передачи данных между контроллерами с помощью Notifications.

Эта функция вызывается каждый раз, когда вы переключаете вкладки. Это делает недействительным таймер, останавливает тикинг и экономит время в миллисекундах.

override func viewWillDisappear(_ animated: Bool) { 

    restTimer.invalidate() 

    let df = DateFormatter() 
    df.dateFormat = "y-MM-dd H:m:ss.SSSS" 

    let disappearingDate = Date() 
    let disappearingDateInMilliseconds = df.string(from: disappearingDate) 

    NotificationCenter.default.post(name: NSNotification.Name(rawValue: "kViewDidChangeExampleNotification"), object: disappearingDateInMilliseconds) 
} 



/* add your Notification observers in each view controller */ 
override func viewDidLoad() { 
    NotificationCenter.default.addObserver(self, selector: #selector(ViewController.handleTimerCallback(notification:)), name: NSNotification.Name(rawValue: "kViewDidChangeExampleNotification"), object: nil) 
} 

Вы должны определить функцию, которая будет обрабатывать уведомления в каждом контроллере:

func handleTimerCallback(notification: NSNotification) { 
    if let dateString = notification.object as? String { 
     print("Object is an String: \(notification.object)") 

     resumeTimerWithDate(dateString) 
    } else { 
     print("Object is not of type String: \(notification.object)") 
    } 
} 

Быстрый пример сравнения дат в Swift по миллисекундах:

func resumeTimerWithDate(dateString: String) { 
    let df = DateFormatter() 
    df.dateFormat = "y-MM-dd H:m:ss.SSSS" 

    let secondDate = Date() 
    let secondDateToStr = df.string(from: secondDate) 

    if dateString < secondDateToStr { 
     print("RESUMING THE TIMER") 
     let resumeDate = df.date(from: dateString) 
     self.createTimer(resumeDate) 
    } else { 
     print("TIMER HAS FINISHED") 
    } 
} 

Другие вещи, чтобы рассмотреть: Возможно, вы захотите добавить некоторые инструкции печати для проверки отладки/проверки работоспособности, поскольку некоторые функции могут срабатывать перед другими. Например, вместо публикации уведомления в viewWillDisappear, вы можете попробовать разместить его в viewDidDisappear или используя prepare(for segue:).

+0

Имеет смысл, хотя я удалил его, и он все еще зависает при изменении вкладок! Хотя думать об этом, таймер останова предназначен для недействительности здесь, поэтому он может восстановить после возобновления вкладки в зависимости от времени, которое он захватывает, когда он делает недействительными. – jwarris91

+0

Хм, я вижу. Пробовали ли вы передавать объект таймера взад и вперед по каждому контроллеру с помощью 'prepareForSegue' или' NSNotificationCenter'? –

+0

Отредактируйте Редактировать # 1 в моем сообщении. Дайте быстрый пример о том, как передавать данные между контроллерами с помощью «NotificationCenter». –