iOS的使用Swift,NSOperation实现的倒计时

栏目: IOS · 发布时间: 6年前

内容简介:iOS的使用Swift,NSOperation实现的倒计时

前段时间,公司项目有个需求要求实现任务倒计时,头疼死我了,折腾了我老半天,先看最终的实现效果,如下图。当时的需求有两点要求:1、要求在当前任务关卡实现倒计时计算;2、要求在弹出来的tips页面同时也进行倒计时。

iOS的使用Swift,NSOperation实现的倒计时

timeCountDown.gif

一想到倒计时,我们可能想到的解决方案有三种;1、NStimer,2、GCD,3、NSOperation。

1、NSTimer实现倒计时

NSTimer实现计时需要注意,他默认是在runloop中的 NSDefaultRunLoopMode 计时,在这个模式下面,有滑动事件,计时将失效,此时我们需要在将timer添加到runloop中的 NSRunLoopCommonModes ,这样就不会有任何影响

let animationTimer = NSTimer.scheduledTimerWithTimeInterval(10, target: self, selector: #selector(WeeklyMissionViewController.runanimation), userInfo: nil, repeats: true) NSRunLoop.mainRunLoop().addTimer(animationTimer!, forMode: NSRunLoopCommonModes) animationTimer!.fire()

2、GCD实现倒计时

GCD实现计时需要注意的是 let _timer: dispatch_source_t 必须存储为全局变量 timer = _timer

private func setGCDTimer(weeklyMission: MissionList, type: Int) {         // 计算倒计时         let nowDate =  NSDate()         let nowUnix = nowDate.timeIntervalSince1970          let count = (weeklyMission.createdAt)! + 24 * 3600 - Int(nowUnix)                 var _timeout: Int = count         let _queue: dispatch_queue_t = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)         let _timer: dispatch_source_t = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, _queue)         timer = _timer         // 每秒执行         dispatch_source_set_timer(_timer, dispatch_walltime(nil, 0), 1 * NSEC_PER_SEC, 0)          printLog("----_timer-----")         dispatch_source_set_event_handler(_timer) { () -> Void in              if _timeout <= 0 {                 // 倒计时结束                 dispatch_source_cancel(_timer)                 dispatch_async(dispatch_get_main_queue(), { [unowned self] () -> Void in                     // 如需更新UI 代码请写在这里                     })             } else {                  print("cell:\(weeklyMission.mission)---\(_timeout)")                 _timeout -= 1                 let hours = _timeout / 3600                 let hoursSec = hours * 3600                 let minutes = (_timeout - hoursSec) / 60                 let seconds = _timeout - hoursSec - minutes * 60                  dispatch_async(dispatch_get_main_queue(), {  [unowned self] in                     let timeText = "\(String(format: "%.2d",hours)):\(String(format: "%.2d",minutes)):\(String(format: "%.2d",seconds))"                     // 如需更新UI 代码请写在这里                     })             }         }         dispatch_resume(_timer)     }

3、NSOperation实现倒计时以上两种实现的计时,有个很明显的缺点就是,不可控!他们二者开启一个计时器之后,没法方便的控制他停止,继续;但是NSOperation不同,他有cancel方法,我们可以拿到对应的operation,然后操作他,可控性好。主要代码如下:

// //  TimeCountDownManager.swift //  leapParent // //  Created by romance on 16/9/19. //  Copyright © 2016年 Firstleap. All rights reserved. //  import UIKit  /// 计时中回调 typealias TimeCountingDownTaskBlock = (timeInterval: NSTimeInterval) -> Void // 计时结束后回调 typealias TimeFinishedBlock = (timeInterval: NSTimeInterval) -> Void private var shareInstance = TimeCountDownManager()  final class TimeCountDownManager: NSObject {     // 单利     class var sharedInstance : TimeCountDownManager {         return shareInstance     }      var pool: NSOperationQueue      override init() {         pool = NSOperationQueue()         super.init()     }      /**      *  开始倒计时,如果倒计时管理器里具有相同的key,则直接开始回调。      *      *  @param Key         任务key,用于标示唯一性      *  @param timeInterval 倒计时总时间,      *  @param countingDown 倒计时时,会多次回调,提供当前秒数      *  @param finished     倒计时结束时调用,提供当前秒数,值恒为 0      */     func scheduledCountDownWith(key: String, timeInteval: NSTimeInterval, countingDown:TimeCountingDownTaskBlock?,finished:TimeCountingDownTaskBlock?) {          var task: TimeCountDownTask?         if coundownTaskExistWith(key, task: &task) {             task?.countingDownBlcok = countingDown             task?.finishedBlcok = finished             if countingDown != nil {                 countingDown!(timeInterval: (task?.leftTimeInterval) ?? 60)             }         } else {             task = TimeCountDownTask()             task?.leftTimeInterval = timeInteval             task?.countingDownBlcok = countingDown             task?.finishedBlcok = finished             task?.name = key              pool.addOperation(task!)         }     }      /**      *  查询倒计时任务是否存在      *      *  @param akey 任务key      *  @param task 任务      *  @return YES - 存在, NO - 不存在      */     func coundownTaskExistWith(key: String,inout task: TimeCountDownTask? ) -> Bool {         var taskExits = false          for (_, obj)  in pool.operations.enumerate() {             let temptask = obj as! TimeCountDownTask             if temptask.name == key {                 task = temptask                 taskExits = true //                print("coundownTaskExistWith#####\(temptask.leftTimeInterval)")                 break             }         }         return taskExits     }      /**      *  取消所有倒计时任务      */     func cancelAllTask() {         pool.cancelAllOperations()     }      /**      *  挂起所有倒计时任务      */     private func suspendAllTask() {         pool.suspended = true     } }   final class TimeCountDownTask: NSOperation {     var leftTimeInterval: NSTimeInterval = 0     var countingDownBlcok: TimeCountingDownTaskBlock?     var finishedBlcok: TimeFinishedBlock?      override func main() {          if self.cancelled {             return         }                 while leftTimeInterval > 0 {             print("leftTimeInterval----\(leftTimeInterval)")              if self.cancelled {                 return             }             leftTimeInterval -= 1             dispatch_async(dispatch_get_main_queue(), {                 if self.countingDownBlcok != nil {                     self.countingDownBlcok!(timeInterval: self.leftTimeInterval)                 }             })             NSThread.sleepForTimeInterval(1)         }          dispatch_async(dispatch_get_main_queue()) {             if self.cancelled {                 return             }             if self.finishedBlcok != nil {                 self.finishedBlcok!(timeInterval: 0)             }         }     } }

稍微解析下以上代码, TimeCountDownManager 是定时器管理类,是个单利,可以管理app中所有需要倒计时的task, TimeCountDownTask 是具体的用来处理倒计时的NSOperation子类,大家还可以在我的基础上进行完善,比如cancel具体taskIdentifier的task,suspended具体的task,等等!

整个demo代码的GitHub地址,希望对大家有用,喜欢的希望大家点赞,评论,转发,关注我啊!让文章下面的:hearts:点亮哦!


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

ANSI Common Lisp

ANSI Common Lisp

Paul Graham / Prentice Hall / 1995-11-12 / USD 116.40

For use as a core text supplement in any course covering common LISP such as Artificial Intelligence or Concepts of Programming Languages. Teaching students new and more powerful ways of thinking abo......一起来看看 《ANSI Common Lisp》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具