AutoSaveManager.swift 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. //
  2. // AutoSaveManager.swift
  3. // PDF Reader Pro
  4. //
  5. // Created by tangchao on 2023/11/8.
  6. //
  7. import Cocoa
  8. public let KAutoSaveTimeValueChangedNoti = "KAutoSaveTimeValueChangedNoti"
  9. @objcMembers class AutoSaveManager: NSObject {
  10. public static let kTimeValueChangedNotificationName = Notification.Name(KAutoSaveTimeValueChangedNoti)
  11. //APP是否允许进行自动缓存
  12. var autoSaveEnabled = false {
  13. didSet {
  14. UserDefaults.standard.setValue(self.autoSaveEnabled, forKey: "ComAutoSaveKey")
  15. UserDefaults.standard.synchronize()
  16. }
  17. }
  18. var timeInterval: CGFloat = 15 {
  19. didSet {
  20. UserDefaults.standard.setValue(Float(self.timeInterval), forKey: "AutoSaveTimeIntervalKey")
  21. UserDefaults.standard.synchronize()
  22. }
  23. }
  24. //防止重复弹出
  25. var autoSaveAlertShow = false
  26. var autoSaveDidEndAction = false
  27. // /当前是否正在保存
  28. var isSaving = false
  29. var isSaveNoti = false
  30. private var _autoSaveFolder: String = ""
  31. var autoSaveFolder: String {
  32. get {
  33. return self._autoSaveFolder
  34. }
  35. }
  36. private var _infoDict: NSMutableDictionary?
  37. // 保存的原文件信息
  38. private var _originalPaths: NSMutableArray?
  39. var originalPaths: NSMutableArray? {
  40. get {
  41. return self._originalPaths
  42. }
  43. }
  44. // 对应保存的信息
  45. private var _autoSavePaths: NSMutableArray?
  46. var autoSavePaths: NSMutableArray? {
  47. get {
  48. return self._autoSavePaths
  49. }
  50. }
  51. // 所有打开的文件信息汇总
  52. var opendPaths: NSMutableArray? {
  53. get {
  54. return self._opendPaths
  55. }
  56. }
  57. private var _opendPaths: NSMutableArray?
  58. static let manager: AutoSaveManager = {
  59. let man = AutoSaveManager()
  60. man.autoSaveEnabled = UserDefaults.standard.bool(forKey: "ComAutoSaveKey")
  61. let timeInterval = UserDefaults.standard.float(forKey: "AutoSaveTimeIntervalKey")
  62. if timeInterval > 0 {
  63. man.timeInterval = timeInterval.cgFloat
  64. } else {
  65. man.timeInterval = 15
  66. }
  67. man._loadData()
  68. man.autoSaveDidEndAction = true
  69. return man
  70. }()
  71. // MARK: - Public Method
  72. func clearCache() {
  73. if FileManager.default.fileExists(atPath: self.autoSaveFolder) {
  74. try?FileManager.default.removeItem(atPath: self.autoSaveFolder)
  75. }
  76. if FileManager.default.fileExists(atPath: self.autoSaveFolder) == false {
  77. try?FileManager.default.createDirectory(atPath: self.autoSaveFolder, withIntermediateDirectories: true)
  78. }
  79. }
  80. func autoSaveWithPath(_ filePath: String) -> String {
  81. let autoSaveFolder = self.autoSaveFolder
  82. let plistPath = String(format: "%@/autoSaveInfo.plist", autoSaveFolder)
  83. var savePath = String(format: "%@/%@_%@.%@", autoSaveFolder, filePath.deletingPathExtension.lastPathComponent, "recovered", filePath.customPathExtension)
  84. if FileManager.default.fileExists(atPath: plistPath) {
  85. var dict = NSMutableDictionary(contentsOfFile: plistPath)
  86. if let keys = dict?.allKeys as? [String], keys.contains(filePath) {
  87. savePath = dict?.value(forKey: filePath) as? String ?? ""
  88. }
  89. if savePath.isEmpty == false && filePath.isEmpty == false {
  90. if let values = dict?.allValues as? [String], values.contains(savePath) {
  91. //不同路径下同名文件的保存覆盖的情况处理
  92. var values = NSArray(array: values)
  93. for key in dict?.allKeys ?? [] {
  94. guard let _key = key as? String else {
  95. continue
  96. }
  97. let value = dict?.object(forKey: key) as? String ?? ""
  98. if savePath == value && _key != filePath {
  99. var count = 1
  100. savePath = String(format: "%@/%@_%@(%d).%@", autoSaveFolder, filePath.deletingPathExtension.lastPathComponent, "recovered", count, filePath.customPathExtension)
  101. while values.contains(savePath) {
  102. count += 1
  103. savePath = String(format: "%@/%@_%@(%d).%@", autoSaveFolder, filePath.deletingPathExtension.lastPathComponent, "recovered", count, filePath.customPathExtension)
  104. }
  105. }
  106. }
  107. }
  108. dict?.setValue(savePath, forKey: filePath)
  109. }
  110. try?dict?.write(to: URL(fileURLWithPath: plistPath))
  111. } else {
  112. var dict = NSMutableDictionary()
  113. if savePath.isEmpty == false && filePath.isEmpty == false {
  114. dict.setValue(savePath, forKey: filePath)
  115. }
  116. try?dict.write(to: URL(fileURLWithPath: plistPath))
  117. }
  118. return savePath
  119. }
  120. func removeAutoSavePath(_ filePath: String) {
  121. let autoSaveFolder = self.autoSaveFolder
  122. let plistPath = String(format: "%@/autoSaveInfo.plist", autoSaveFolder)
  123. if FileManager.default.fileExists(atPath: plistPath) {
  124. var dict = NSMutableDictionary(contentsOfFile: plistPath)
  125. if let savePath = dict?.value(forKey: filePath) as? String {
  126. if FileManager.default.fileExists(atPath: savePath) {
  127. try?FileManager.default.removeItem(atPath: savePath)
  128. }
  129. dict?.removeObject(forKey: filePath)
  130. }
  131. if let keys = dict?.allKeys, keys.count > 0 {
  132. try?dict?.write(to: URL(fileURLWithPath: plistPath))
  133. } else {
  134. try?FileManager.default.removeItem(atPath: plistPath)
  135. }
  136. }
  137. }
  138. // MARK: - Private Methods
  139. private func _loadData() {
  140. var cachesPath = NSSearchPathForDirectoriesInDomains(.cachesDirectory, .userDomainMask, true).first ?? ""
  141. let filepath = "\(cachesPath)/\(Bundle.main.bundleIdentifier ?? "")"
  142. if FileManager.default.fileExists(atPath: filepath) {
  143. cachesPath = filepath
  144. }
  145. cachesPath = "\(cachesPath)/autoSaveFolder"
  146. if FileManager.default.fileExists(atPath: cachesPath) == false {
  147. try?FileManager.default.createDirectory(atPath: cachesPath, withIntermediateDirectories: true)
  148. }
  149. self._autoSaveFolder = cachesPath
  150. KMPrint("autoSaveFolder===\(cachesPath)")
  151. let plistPath = String(format: "%@/autoSaveInfo.plist", self.autoSaveFolder)
  152. guard let dict = NSMutableDictionary(contentsOfFile: plistPath) else {
  153. return
  154. }
  155. if (dict.allKeys.count == 0) {
  156. return
  157. }
  158. self._infoDict = dict
  159. if (self._autoSavePaths == nil) {
  160. self._autoSavePaths = NSMutableArray()
  161. }
  162. if (self._originalPaths == nil) {
  163. self._originalPaths = NSMutableArray()
  164. }
  165. self._originalPaths?.addObjects(from: dict.allKeys)
  166. self._opendPaths = NSMutableArray()
  167. var arr = (try?FileManager.default.contentsOfDirectory(atPath: self.autoSaveFolder)) ?? []
  168. for fileName in arr {
  169. let savedKey = "\(self.autoSaveFolder)/\(fileName)"
  170. guard let values = dict.allValues as? [String] else {
  171. continue
  172. }
  173. if values.contains(savedKey) {
  174. self.autoSavePaths?.add(savedKey)
  175. } else {
  176. if fileName == "autoSaveInfo.plist" {
  177. } else {
  178. try?FileManager.default.removeItem(atPath: savedKey)
  179. }
  180. }
  181. }
  182. }
  183. /*
  184. - (NSString *)URLEncodedString:(NSString *)string {
  185. CFStringRef stringRef = CFBridgingRetain(string);
  186. #pragma clang diagnostic push
  187. #pragma clang diagnostic ignored "-Wdeprecated-declarations"
  188. CFStringRef encoded = CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault,
  189. stringRef,
  190. NULL,
  191. CFSTR("!*'\"();:@&=+$,/?%#[]% "),
  192. kCFStringEncodingUTF8);
  193. #pragma clang diagnostic pop
  194. CFRelease(stringRef);
  195. return CFBridgingRelease(encoded);
  196. }
  197. - (NSString *)getValidFilePath:(NSString *)oldPath {
  198. NSFileManager *fileManager = [NSFileManager defaultManager];
  199. NSDictionary *fileDic = [fileManager attributesOfItemAtPath:oldPath error:nil];
  200. NSString *fileType = [fileDic objectForKey:NSFileType];
  201. int i =1;
  202. NSString *newPath = oldPath;
  203. while ([fileManager fileExistsAtPath:newPath]) {
  204. if ([fileType isEqualToString:NSFileTypeDirectory]) {
  205. newPath = [oldPath stringByAppendingFormat:@"(%d)",i];
  206. } else {
  207. NSString *fileExtension = [oldPath pathExtension];
  208. newPath = [[oldPath stringByDeletingPathExtension] stringByAppendingFormat:@"(%d).%@",i,fileExtension];
  209. }
  210. i++;
  211. }
  212. return newPath;
  213. }
  214. */
  215. }