TSCommonTool.swift 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. //
  2. // TSCommonTool.swift
  3. // TSLiveWallpaper
  4. //
  5. // Created by 100Years on 2024/12/20.
  6. //
  7. import Kingfisher
  8. import Foundation
  9. import AVFoundation
  10. class TSCommonTool {
  11. //
  12. // static func downLoadImage(_ urlStr:String, completion: @escaping (_ image:UIImage) -> Void) {
  13. // ImageDownloader.default.downloadImage(with: URL(string: urlStr)!, options: nil) { receivedSize, totalSize in
  14. // debugPrint(receivedSize)
  15. // } completionHandler: {
  16. // result in
  17. // switch result {
  18. // case .success(let value):
  19. // completion(value.image)
  20. // case .failure(let error):
  21. // print(error)
  22. // }
  23. // }
  24. // }
  25. //
  26. /// 下载图片,优先从缓存中取,支持设置缓存策略
  27. /// - Parameters:
  28. /// - url: 图片的 URL 地址
  29. /// - completion: 完成回调,返回图片或错误
  30. static func fetchImageWithCache(
  31. from urlString: String,
  32. completion: @escaping (UIImage?, Error?) -> Void
  33. ) {
  34. guard let url = URL(string: urlString) else{
  35. completion(nil, NSError(domain: "url null", code: 0))
  36. return
  37. }
  38. // 配置 Kingfisher 的缓存策略
  39. let options: KingfisherOptionsInfo = [
  40. .cacheOriginalImage,
  41. .memoryCacheExpiration(.days(7)), // 内存缓存时间
  42. .diskCacheExpiration(.days(30)), // 磁盘缓存时间
  43. .cacheSerializer(DefaultCacheSerializer.default)
  44. ]
  45. // 使用 Kingfisher 检查缓存是否存在
  46. let cache = ImageCache.default
  47. let cacheKey = url.absoluteString
  48. cache.retrieveImage(forKey: cacheKey, options: nil) { result in
  49. switch result {
  50. case .success(let value):
  51. if let image = value.image {
  52. // 从缓存中取到图片
  53. completion(image, nil)
  54. } else {
  55. // 缓存中不存在图片,进行下载
  56. downloadImage(from: url, options: options, completion: completion)
  57. }
  58. case .failure(let error):
  59. // 缓存检查失败,直接下载
  60. print("缓存检查失败: \(error.localizedDescription)")
  61. downloadImage(from: url, options: options, completion: completion)
  62. }
  63. }
  64. }
  65. /// 获取已缓存的磁盘图片文件路径
  66. /// - Parameters:
  67. /// - urlString: 图片的 URL 地址
  68. /// - completion: 完成回调,返回图片的磁盘路径或错误
  69. static func fetchImagePathWithCache(
  70. from urlString: String,
  71. completion: @escaping (String?, Error?) -> Void
  72. ) {
  73. guard let url = URL(string: urlString) else {
  74. completion(nil, NSError(domain: "InvalidURL", code: 0, userInfo: [NSLocalizedDescriptionKey: "无效的 URL"]))
  75. return
  76. }
  77. let cache = ImageCache.default
  78. let cacheKey = url.absoluteString
  79. if cache.isCached(forKey: cacheKey) {
  80. completion(cache.cachePath(forKey: cacheKey), nil)
  81. }else {
  82. completion(nil, NSError(domain: "CachePathError", code: 1, userInfo: [NSLocalizedDescriptionKey: "无法获取缓存路径"]))
  83. }
  84. }
  85. /// 下载图片并缓存
  86. /// - Parameters:
  87. /// - url: 图片的 URL 地址
  88. /// - options: Kingfisher 下载和缓存的选项
  89. /// - completion: 完成回调,返回图片或错误
  90. static func downloadImage(
  91. from url: URL,
  92. options: KingfisherOptionsInfo,
  93. completion: @escaping (UIImage?, Error?) -> Void
  94. ) {
  95. KingfisherManager.shared.retrieveImage(with: url, options: options,progressBlock: { receivedSize, totalSize in
  96. debugPrint(receivedSize)
  97. }) { result in
  98. switch result {
  99. case .success(let value):
  100. completion(value.image, nil)
  101. case .failure(let error):
  102. completion(nil, error)
  103. }
  104. }
  105. }
  106. /// 下载并缓存文件,依据 URL 的后缀名动态设置文件名
  107. /// - Parameters:
  108. /// - url: 文件的 URL 地址
  109. /// - completion: 完成回调,返回本地缓存路径或错误
  110. static func downloadAndCacheFile(from urlString: String, fileEx:String? = nil, cacheDirectory:String = "cacheVideo",completion: @escaping (String?, Error?) -> Void) {
  111. guard let url = URL(string: urlString) else{
  112. completion(nil, NSError(domain: "url null", code: 0))
  113. return
  114. }
  115. if !urlString.contains("http") && urlString.contains("/"){
  116. completion(urlString.fillCachePath, nil)
  117. return
  118. }
  119. let fileManager = FileManager.default
  120. // 获取缓存目录下的 `cacheVideo` 文件夹路径
  121. let cacheDirectory = fileManager.urls(for: .cachesDirectory, in: .userDomainMask).first!
  122. let cacheVideoDirectory = cacheDirectory.appendingPathComponent("cacheVideo")
  123. // 创建 `cacheVideo` 文件夹(如果不存在)
  124. if !fileManager.fileExists(atPath: cacheVideoDirectory.path) {
  125. do {
  126. try fileManager.createDirectory(at: cacheVideoDirectory, withIntermediateDirectories: true, attributes: nil)
  127. } catch {
  128. completion(nil, error)
  129. return
  130. }
  131. }
  132. // 使用 URL 的 MD5 哈希值作为缓存文件名,附加 URL 的后缀名
  133. var fileExtension = fileEx
  134. fileExtension = fileExtension ?? (url.pathExtension.isEmpty ? "tmp" : url.pathExtension)
  135. let fileName = url.path.md5 + ".\(fileExtension!)"
  136. let cachedFileURL = cacheVideoDirectory.appendingPathComponent(fileName)
  137. // 检查文件是否已存在于缓存中
  138. if fileManager.fileExists(atPath: cachedFileURL.path) {
  139. print("文件已存在于缓存中: \(cachedFileURL)")
  140. completion(cachedFileURL.path, nil)
  141. return
  142. }
  143. // 下载文件
  144. let task = URLSession.shared.downloadTask(with: url) { tempFileURL, response, error in
  145. if let error = error {
  146. completion(nil, error)
  147. return
  148. }
  149. guard let tempFileURL = tempFileURL else {
  150. completion(nil, NSError(domain: "DownloadError", code: -1, userInfo: [NSLocalizedDescriptionKey: "临时文件路径不存在"]))
  151. return
  152. }
  153. do {
  154. try fileManager.moveItem(at: tempFileURL, to: cachedFileURL)
  155. print("文件下载并缓存成功: \(cachedFileURL)")
  156. completion(cachedFileURL.path, nil)
  157. } catch {
  158. completion(nil, error)
  159. }
  160. }
  161. task.resume()
  162. }
  163. }
  164. let kMainQueue = DispatchQueue.main
  165. /// 主线程延迟执行回调
  166. /// - Parameters:
  167. /// - delay: 延迟时间(秒)
  168. /// - completion: 延迟后的回调
  169. func kDelayOnMainThread(_ delay: TimeInterval, completion: @escaping () -> Void) {
  170. DispatchQueue.main.asyncAfter(deadline: .now() + delay) {
  171. completion()
  172. }
  173. }
  174. func kDelayMainShort(completion: @escaping () -> Void) {
  175. DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
  176. completion()
  177. }
  178. }
  179. /// 在主线程上执行代码
  180. /// - Parameter block: 要执行的代码块
  181. func kExecuteOnMainThread(_ block: @escaping () -> Void) {
  182. if Thread.isMainThread {
  183. block()
  184. } else {
  185. DispatchQueue.main.async {
  186. block()
  187. }
  188. }
  189. }
  190. let kAppName:String = "Ghiblix"