В моей реализации я запускаю сразу несколько таймеров в 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 singleton выше. Ниже мое удаление логика:
//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 состоит из:
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
}
}
инстанцирования TimerObject:
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
}
}
}
Я искренне надеюсь, что это достаточно информации, чтобы работать. Любые решения или альтернативы очень помогли бы.
Никогда не делать 'таймер вар = NSTimer()'. Вы не показываете пример создания и использования 'TimerObject'. Ваш вопрос лучше, чем вчера, но вы должны действительно объяснить, как вы используете этот класс, и какова ваша фактическая цель пользователя - почему у вас много таймеров, почему бы нет 1 таймера и объектов, которые имеют «огонь до истек» или просто NSDate, когда они истекают? – Wain
Извините, я не уверен, как показать использование объекта таймера без скриншота приложения. Я объясню как можно лучше. Пользователь нажимает на ссылку, которая сопоставляется с действием, которое уведомляет одинарный сигнал, чтобы запустить таймер на X минут, функция таймера запуска затем создает новую ячейку в таблице, отображающую рабочий таймер. Я использую NSTimer для уведомления persistTimer, чтобы сообщить tableView обновить ячейку с новым уменьшенным временем. Пользователь может запустить любое количество таймеров, и они могут активировать таймер любое количество раз, это ограничения. –
Использование NSDate не позволит мне обновлять tableView каждую секунду. Кроме того, можете ли вы подробнее рассказать о том, почему 'var timer = NSTimer()' является табу? –