内容简介: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
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Think Python
Allen B. Downey / O'Reilly Media / 2012-8-23 / GBP 29.99
Think Python is an introduction to Python programming for students with no programming experience. It starts with the most basic concepts of programming, and is carefully designed to define all terms ......一起来看看 《Think Python》 这本书的介绍吧!