定时器控件,上传图片指定类型
This commit is contained in:
189
Pods/DDTimer/DDTimer/Classes/GCDTimer/GCDTimer.swift
generated
Normal file
189
Pods/DDTimer/DDTimer/Classes/GCDTimer/GCDTimer.swift
generated
Normal file
@@ -0,0 +1,189 @@
|
||||
//
|
||||
// GCDTimer.swift
|
||||
// DDTimer
|
||||
// Created by DDIsFriend on 2023/9/15.
|
||||
|
||||
|
||||
import Foundation
|
||||
import DDLog
|
||||
|
||||
public let GCDT = GCDTimer.default
|
||||
open class GCDTimer {
|
||||
public static let `default` = GCDTimer()
|
||||
|
||||
private var timerSources : [GCDTimerAbstract] = []
|
||||
|
||||
private var timerAddOrRemoveQueue = DispatchQueue(label: "GCDTimerAddOrRemoveQueue") // 移除定时器的时候,由于存在多个定时器同时移除的情况,定时器本身是异步操作的,所以从timerSources中移除GCDTimerAbstract的操作也是异步的,这就会导致数组在遍历的同时也在从数组中删除项目,会有问题,所以把删除的操作放在同步队列中
|
||||
|
||||
/// 取消定时器时,定时器如果有正在执行的任务,会先将当前正在执行的任务执行完成才会取消成功,因此如果需要添加相同名字的定时器,需要确保之前同名的定时器已经被彻底取消了。
|
||||
/// - Parameters:
|
||||
/// - named: 定时器名字
|
||||
/// - delay: 定时器延迟多久开始执行第一次操作
|
||||
/// - repeating: 定时器间隔时间
|
||||
/// - repeatCount: 重复次数
|
||||
/// - repeatHandler: 定时器操作
|
||||
/// - cancelHandler: 如果执行了cancelHandler,就不会执行completionHandler
|
||||
/// - completionHandler: 如果执行了completionHandler,就不会执行cancelHandler
|
||||
public func addGCDTimer(named timerName:String,delay:DispatchTimeInterval,repeating:DispatchTimeInterval,repeatCount:Int = Int.max,repeatHandler:@escaping (() -> Void),cancelHandler:(() -> Void)? = nil,completionHandler:(() -> Void)? = nil) {
|
||||
timerAddOrRemoveQueue.async { [weak self] in
|
||||
if let _ = self?.timerSources.first(where: { gcdTimerA in
|
||||
gcdTimerA.timerName == timerName
|
||||
}) {
|
||||
DDLog(message: "定时器\'\(timerName)\'重复添加,添加失败")
|
||||
return
|
||||
}
|
||||
|
||||
let gcdTimerA = GCDTimerAbstract(named: timerName)
|
||||
gcdTimerA.addGCDTimer(delay: delay, repeating: repeating, repeatCount: repeatCount) {
|
||||
repeatHandler()
|
||||
} cancelHandler: {[weak self] (timerName,canceledCompletionHandler) in
|
||||
// 移除定时器
|
||||
self?.removeGCDTimer(named: timerName,removeComletionHandler: {
|
||||
// 添加定时器处执行取消操作
|
||||
if let cancelHandler {
|
||||
cancelHandler()
|
||||
}
|
||||
// 取消定时器处执行取消操作
|
||||
if let canceledCompletionHandler {
|
||||
canceledCompletionHandler()
|
||||
}
|
||||
})
|
||||
} completionHandler: {[weak self] (timerName,canceledCompletionHandler) in
|
||||
// 移除定时器
|
||||
self?.removeGCDTimer(named: timerName,removeComletionHandler: {
|
||||
// 执行结束操作
|
||||
if let completionHandler {
|
||||
completionHandler()
|
||||
}
|
||||
// 这是一种特殊的情况,当且仅当主动取消定时器时,定时器正在进行最后一次任务操作
|
||||
if let canceledCompletionHandler {
|
||||
canceledCompletionHandler()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
self?.timerSources.append(gcdTimerA)
|
||||
DDLog(message: "定时器\'\(timerName)\'添加成功")
|
||||
// 打印剩余的定时器
|
||||
self?.logTimerName()
|
||||
}
|
||||
}
|
||||
|
||||
func removeGCDTimer(named timerName:String,removeComletionHandler:@escaping () -> Void) {
|
||||
timerAddOrRemoveQueue.async { [weak self] in
|
||||
// 移除定时器的抽象类
|
||||
if let index = self?.timerSources.firstIndex(where: { gcdTimerA in
|
||||
gcdTimerA.timerName == timerName
|
||||
}) {
|
||||
self?.timerSources.remove(at: index)
|
||||
DDLog(message: "定时器\'\(timerName)\'移除成功")
|
||||
|
||||
// 异步操作回调
|
||||
DispatchQueue.global().async {
|
||||
removeComletionHandler()
|
||||
}
|
||||
}
|
||||
// 打印剩余的定时器
|
||||
self?.logTimerName()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// 在取消定时器时,假如定时器正在执行任务,这个过程中被多次取消且携带了canceledCompletionHandler,只会执行最后一次赋值的canceledCompletionHandler。
|
||||
/// - Parameters:
|
||||
/// - timerName: 定时器名字
|
||||
/// - canceledCompletionHandler: 取消定时器后的操作
|
||||
public func cancelGCDTimer(named timerName:String,canceledCompletionHandler:(() -> Void)? = nil) {
|
||||
timerAddOrRemoveQueue.async {[weak self] in
|
||||
// 当timerSources中包含定时器时,取消定时器
|
||||
if let gcdTimerA = self?.timerSources.first(where: { gcdTimerA in
|
||||
gcdTimerA.timerName == timerName
|
||||
}) {
|
||||
gcdTimerA.canceledCompletionHandler = canceledCompletionHandler
|
||||
gcdTimerA.cancelGCDTimer(isCanceledManually: true)
|
||||
}else{
|
||||
// 异步操作回调
|
||||
DispatchQueue.global().async {
|
||||
if let canceledCompletionHandler {
|
||||
canceledCompletionHandler()
|
||||
}
|
||||
}
|
||||
// 打印剩余的定时器
|
||||
self?.logTimerName()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func containsGCDTimer(named timerName:String) -> Bool {
|
||||
if let _ = timerSources.first(where: { gcdTimerA in
|
||||
gcdTimerA.timerName == timerName
|
||||
}) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func logTimerName() {
|
||||
var array : [String] = []
|
||||
for gcdTimerA in timerSources {
|
||||
array.append(gcdTimerA.timerName)
|
||||
}
|
||||
DDLog(message:("剩余定时器:\'\(array)\'"))
|
||||
array.removeAll()
|
||||
}
|
||||
}
|
||||
|
||||
class GCDTimerAbstract {
|
||||
|
||||
private let timerSource = DispatchSource.makeTimerSource(flags: .strict,queue: DispatchQueue(label: "GCDTimerAbstract.makeTimerSource",attributes: [.concurrent]))
|
||||
|
||||
public var timerName : String
|
||||
|
||||
public var isCanceledManually : Bool = false // 是否时主动取消定时器
|
||||
|
||||
public var canceledCompletionHandler:(() -> Void)? // 主动取消定时器时,由于定时器当前可能存在任务,所以要等任务结束后再进行相应的操作
|
||||
|
||||
init(named timerName: String) {
|
||||
self.timerName = timerName
|
||||
}
|
||||
|
||||
public func addGCDTimer(delay:DispatchTimeInterval,repeating:DispatchTimeInterval,repeatCount:Int,repeatHandler:@escaping (() -> Void),cancelHandler:((String,(() -> Void)?) -> Void)? = nil,completionHandler: ((String,(() -> Void)?) -> Void)? = nil) {
|
||||
// 当前剩余的次数
|
||||
var leftRepeatCount = repeatCount
|
||||
|
||||
timerSource.setEventHandler(handler: {[weak self] in
|
||||
// 定时器执行的任务
|
||||
repeatHandler()
|
||||
|
||||
leftRepeatCount-=1
|
||||
// 此时定时器次数结束
|
||||
if (leftRepeatCount > 0) == false {
|
||||
// 这里有一种特殊情况,当主动cancel了定时器,且在进行最后一次任务的时候,最后一次任务执行完正好来到这里,那么依然要调用canceledCompletionHandler
|
||||
self?.cancelGCDTimer(isCanceledManually: false)
|
||||
}
|
||||
})
|
||||
|
||||
timerSource.setCancelHandler(handler: {[weak self] in
|
||||
if self?.isCanceledManually == true {
|
||||
// 定时器中途被取消时,在添加定时器的位置需要执行的取消操作
|
||||
if let cancelHandler,let timerName = self?.timerName {
|
||||
cancelHandler(timerName,self?.canceledCompletionHandler)
|
||||
}
|
||||
}else{
|
||||
// 定时器结束后执行
|
||||
if let completionHandler,let timerName = self?.timerName {
|
||||
completionHandler(timerName,self?.canceledCompletionHandler)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
timerSource.schedule(wallDeadline: DispatchWallTime.now() + delay,repeating: repeating)
|
||||
timerSource.activate()
|
||||
}
|
||||
|
||||
// 次数统一处理结束,因为会有cancelHander
|
||||
public func cancelGCDTimer(isCanceledManually:Bool) {
|
||||
self.isCanceledManually = isCanceledManually
|
||||
timerSource.cancel()
|
||||
}
|
||||
}
|
||||
19
Pods/DDTimer/LICENSE
generated
Normal file
19
Pods/DDTimer/LICENSE
generated
Normal file
@@ -0,0 +1,19 @@
|
||||
Copyright (c) 2023 DDIsFriend <DDIsFriend@163.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
29
Pods/DDTimer/README.md
generated
Normal file
29
Pods/DDTimer/README.md
generated
Normal file
@@ -0,0 +1,29 @@
|
||||
# DDTimer
|
||||
|
||||
[](https://travis-ci.org/DDIsFriend/DDTimer)
|
||||
[](https://cocoapods.org/pods/DDTimer)
|
||||
[](https://cocoapods.org/pods/DDTimer)
|
||||
[](https://cocoapods.org/pods/DDTimer)
|
||||
|
||||
## Example
|
||||
|
||||
To run the example project, clone the repo, and run `pod install` from the Example directory first.
|
||||
|
||||
## Requirements
|
||||
|
||||
## Installation
|
||||
|
||||
DDTimer is available through [CocoaPods](https://cocoapods.org). To install
|
||||
it, simply add the following line to your Podfile:
|
||||
|
||||
```ruby
|
||||
pod 'DDTimer'
|
||||
```
|
||||
|
||||
## Author
|
||||
|
||||
DDIsFriend, DDIsFriend@163.com
|
||||
|
||||
## License
|
||||
|
||||
DDTimer is available under the MIT license. See the LICENSE file for more info.
|
||||
Reference in New Issue
Block a user