2016-07-01 31 views
0

我在執行我上一個UITableView運行多個定時器一次,當一個定時器結束,我無效,並允許它從被刪除暫停執行先前的計時器後運行的所有NSTimers說的看法。目前我遇到的問題是,當一個定時器被刪除時,所有其他定時器停止執行。已經失效,而不是繼續運行

public class TimerManager{ 
    static let instance = TimerManager() 
    private var delegates = [TimerDelegate]() 
    var currentTimers = [TimerObject]() 

    public func timerAdded(timer: TimerObject){ 
     self.currentTimers.append(timer) 
     timer.timer = NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: #selector(persistTimer(_:)), userInfo: "\(TimerManager.instance.currentTimers.count-1)", repeats: false) 
     timer.isRunning = true 
     for delegate in delegates{ 
      delegate.startTimer(self.currentTimers[self.currentTimers.count-1]) 
     } 
    } 

    @objc public func persistTimer(timer: NSTimer){ 
     if let indexString = timer.userInfo as? String{ 
      if let index = Int(indexString){ 
       if let currentTimer = self.currentTimers[safe: index]{ 
        if currentTimer.isRunning{ 
         currentTimer.timeDuration -= 1 
         for delegate in delegates{ 
          delegate.timerStarted(index) 
         } 
        } 
       } 
      } 
     } 

    } 

    public func addTime(timerId: Int, amount: Int){ 
     for delegate in delegates{ 
      delegate.addTimeToTimer(timerId, amount: amount) 
      UIApplication.sharedApplication().cancelLocalNotification(currentTimers[timerId].notification) 
      currentTimers[timerId].notification.fireDate = NSDate(timeIntervalSinceNow: Double(currentTimers[timerId].timeDuration)) 
     } 
    } 

    public func subtractTime(timerId: Int, amount: Int){ 
     for delegate in delegates{ 
      delegate.subtractTimeFromTimer(timerId, amount: amount) 
      UIApplication.sharedApplication().cancelLocalNotification(currentTimers[timerId].notification) 
      currentTimers[timerId].notification.fireDate = NSDate(timeIntervalSinceNow: Double(currentTimers[timerId].timeDuration)) 
     } 
    } 

    public func removeDelegate(removedDelegate: TimerDelegate){ 
     for i in 0..<delegates.count{ 
      if delegates[i] === removedDelegate{ 
       delegates.removeAtIndex(i) 
      } 
     } 
    } 

    public func cancelTimer(timerId: Int){ 
     let currentTimer = currentTimers[timerId] 
     currentTimer.timer.invalidate() 
     UIApplication.sharedApplication().cancelLocalNotification(currentTimer.notification) 
     currentTimers.removeAtIndex(timerId) 
    } 

    private init() {} 
} 

這是我上面的TimerManager單例。 下面是我刪除邏輯:

//Delete cell functionality 
    public override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) { 
     if(editingStyle == .Delete){ 
      let screenSize: CGRect = UIScreen.mainScreen().bounds 
      let screenWidth = screenSize.width 
      let screenHeight = screenSize.height 
      let deletedTimer = TimerManager.instance.currentTimers[indexPath.row] 
      if (deletedTimer.isRunning){ 
       deletedTimer.timer.invalidate()// <-- invalidates all timers for some reason 
       UIApplication.sharedApplication().cancelLocalNotification(deletedTimer.notification) 
      } 
      TimerManager.instance.currentTimers.removeAtIndex(indexPath.row) 
      self.tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade) 
      self.tableView.frame = CGRect.init(x: 0, y: 100, width: screenWidth, height: screenHeight * 0.0625 * CGFloat(TimerManager.instance.currentTimers.count)) 
     } 
    } 

這是我如何啓動一個定時器:

public func startTimer(timer: TimerObject) { 
     let newIndexPath = NSIndexPath(forRow: TimerManager.instance.currentTimers.count-1, inSection: 0) 
     self.tableView.insertRowsAtIndexPaths([newIndexPath], withRowAnimation: .Bottom) 
     let screenSize: CGRect = UIScreen.mainScreen().bounds 
     let screenWidth = screenSize.width 
     let screenHeight = screenSize.height 
     self.view.frame = CGRectMake(0, 100, screenWidth, screenHeight * 0.0625 * CGFloat(TimerManager.instance.currentTimers.count)) 
     self.view.alpha = 0.95 

    } 

這是我TimerObject所包含的內容:一TimerObject的

public class TimerObject{ 
    var alreadySet = false 
    var isRunning = false 
    var timer = NSTimer() 
    var timeDuration = Int() 
    var timerString = String() 
    var doneString = String() 
    let notification = UILocalNotification() 

    init(timeDuration: Int, timerString: String, doneString: String){ 
     self.timeDuration = timeDuration 
     self.timerString = timerString 
     self.doneString = doneString 
     notification.alertBody = doneString 
    } 
} 

實例化:

private func setTextLinks(string: String){ 
     if let timersForInstruction = parsedOutTimers{ 
      stepTextView.linkTextAttributes = [NSForegroundColorAttributeName : UIColor.redColor()] 
      for timer in timersForInstruction{ 
       stepTextView.addLink(string.substringFromRange(timer.range)) { 
        let newTimer = TimerObject.init(timeDuration: timer.lowerBound * 60, timerString: self.stepTitle 
        newTimer.notification.fireDate = NSDate(timeIntervalSinceNow: Double(newTimer.timeDuration)) 
        TimerManager.instance.timerAdded(newTimer) 
       } 
      } 
      stepTextView.processLinks() 
     } 
    } 

我會說這是它使用的地方:

//where we update the cells 
    public func timerIsRunning(timerIndex: Int){ 
     if let currentTimer = TimerManager.instance.currentTimers[safe: timerIndex]{ 
      guard let cell = self.tableView.cellForRowAtIndexPath(NSIndexPath.init(
       forRow: timerIndex, 
       inSection: 0)) as? TimerCell else { return } 
      if currentTimer.timeDuration > 0{ 
       currentTimer.timeDuration -= 1 
       cell.timerDisplay.text = "\(currentTimer.timerString) \t\t\t - \(currentTimer.timeDuration/60):\((currentTimer.timeDuration % 60).format("02")) + " 
       cell.timerDisplay.processLinks() 
      }else if(currentTimer.timeDuration <= 0){ 
       currentTimer.isRunning = false 
       cell.timerDisplay.text = "Finished" 
       currentTimer.timer.invalidate() 
       currentTimer.notification.fireDate = NSDate(timeIntervalSinceNow: 0) 
       currentTimer.notification.alertBody = currentTimer.doneString 
       currentTimer.notification.alertAction = "Ok" 
       if(self.isBeingPresented()){ 
        NSNotificationCenter.defaultCenter().postNotificationName("timerDidFinish", object: currentTimer.notification.alertBody) 
       } 
       if(UIApplicationState.Background == UIApplication.sharedApplication().applicationState){ 
        UIApplication.sharedApplication().scheduleLocalNotification(currentTimer.notification) 
       } 
      }else{ 
       //handle pause 
      } 
     } 

    } 

我真誠地希望這是足夠的信息來處理。任何解決方案或替代方案都會有很大幫助。

+0

決不做'VAR定時器=的NSTimer()'。你沒有展示創建和使用'TimerObject'的例子。你的問題比昨天好,但你應該真正解釋你如何使用這個類,以及你的實際用戶目標是什麼 - 爲什麼你有很多計時器,爲什麼不有1個計時器和對象持有'火直到過期'或者只是一個NSDate時,他們到期? – Wain

+0

對不起,我不確定如何顯示計時器對象的使用情況,而不顯示應用程序的屏幕截圖。我會盡我所能解釋。用戶點擊一個映射到一個動作的鏈接,該動作通知單例啓動一個X分鐘的計時器,然後啓動計時器函數在顯示正在運行的計時器的表格視圖中創建一個新的單元格。我使用NSTimer通知persistTimer告訴tableView以新遞減的時間更新單元格。用戶可以啓動任意數量的定時器,並且可以激活定時器任意次,這些都是約束條件。 –

+0

使用NSDate不會讓我每秒更新tableView。另外,你可以詳細瞭解爲什麼'var timer = NSTimer()'是禁忌嗎? –

回答

0

我能夠代替實例化一個新的計時器爲每個對象來解決我自己的問題,但只是一個計時器,更新真實所有對象的視圖。

private var timer = NSTimer() 
    var isFirstTimer = false 


    public func timerAdded(newTimerObject: TimerObject){ 
     if(isFirstTimer){ 
      self.timer = NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: #selector(persistTimers(_:)), userInfo: nil, repeats: true) 
     } 
     self.currentTimers.append(newTimerObject) 
     newTimerObject.isRunning = true 
     for delegate in delegates{ 
      delegate.startTimer(self.currentTimers[self.currentTimers.count-1]) 
     } 
    } 

    @objc public func persistTimers(timer: NSTimer){ 
     for i in 0..<self.currentTimers.count{ 
      if let currentTimer = currentTimers[safe: i]{ 
       if(currentTimer.isRunning){ 
        currentTimer.timeDuration -= 1 
        for delegate in delegates{ 
         delegate.timerStarted(i) 
        } 
       } 
      } 
     } 
    } 

這最終是什麼,我結束了在我的單身宣言和 改變我結束了去除的timerStarted功能

currentTimer.timeDuration -= 1 

行成persistTime功能......我知道我的實現和風格有很多不足之處,但這是一個開始。畢竟只有2個星期進入iOS編程。

編輯:

"[safe: ]"擴展我添加是安全的索引訪問:

public extension CollectionType{ 
    subscript (safe index: Index) -> Generator.Element? { 
     return indices.contains(index) ? self[index] : nil 
    } 
}