内容简介:iOS的使用Swift,NSOperation实现的倒计时
前段时间,公司项目有个需求要求实现任务倒计时,头疼死我了,折腾了我老半天,先看最终的实现效果,如下图。当时的需求有两点要求:1、要求在当前任务关卡实现倒计时计算;2、要求在弹出来的tips页面同时也进行倒计时。
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:点亮哦!
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 使用Akka实现并发
- 使用GOLANG实现猴子排序
- 使用 WebSocket 实现 JsBridge
- 使用 RabbitMQ 实现 RPC
- 使用Kafka实现事件溯源
- 使用 Swift 实现 Promise
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。