AutoSaveManager.swift 9.2 KB

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