MessageStatusManager.m 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. //
  2. // MessageStatusManager.m
  3. // AIIM
  4. //
  5. // Created by AI Assistant on 2025/10/21.
  6. //
  7. #import "MessageStatusManager.h"
  8. // plist 文件名
  9. static NSString *const kMessageStatusPlistName = @"MessageStatus.plist";
  10. @interface MessageStatusManager ()
  11. @property (nonatomic, strong) NSMutableDictionary<NSString *, NSNumber *> *statusCache;
  12. @property (nonatomic, strong) dispatch_queue_t ioQueue;
  13. @property (nonatomic, copy) NSString *plistPath;
  14. @end
  15. @implementation MessageStatusManager
  16. #pragma mark - Singleton
  17. + (instancetype)sharedInstance {
  18. static MessageStatusManager *instance = nil;
  19. static dispatch_once_t onceToken;
  20. dispatch_once(&onceToken, ^{
  21. instance = [[self alloc] init];
  22. });
  23. return instance;
  24. }
  25. - (instancetype)init {
  26. self = [super init];
  27. if (self) {
  28. // 创建串行队列用于文件读写,避免并发问题
  29. _ioQueue = dispatch_queue_create("com.aiim.messageStatus.io", DISPATCH_QUEUE_SERIAL);
  30. // 获取 plist 文件路径
  31. _plistPath = [self plistFilePath];
  32. // 加载缓存
  33. [self loadCache];
  34. }
  35. return self;
  36. }
  37. #pragma mark - Public Methods
  38. - (void)saveMessageStatus:(NSInteger)status forMessageId:(NSString *)messageId {
  39. if (!messageId || messageId.length == 0) {
  40. NSLog(@"[MessageStatusManager] 保存失败: messageId 为空");
  41. return;
  42. }
  43. dispatch_async(self.ioQueue, ^{
  44. // 更新内存缓存
  45. self.statusCache[messageId] = @(status);
  46. // 保存到文件
  47. [self saveCacheToDisk];
  48. NSLog(@"[MessageStatusManager] 保存成功: messageId=%@, status=%ld", messageId, (long)status);
  49. });
  50. }
  51. - (NSInteger)getMessageStatusForMessageId:(NSString *)messageId {
  52. if (!messageId || messageId.length == 0) {
  53. NSLog(@"getMessageStatusForMessageId 1: 1");
  54. return 1; // 默认返回发送成功
  55. }
  56. if (![self.statusCache.allKeys containsObject:messageId]) {
  57. NSLog(@"getMessageStatusForMessageId 2: 1");
  58. return 0;
  59. }
  60. __block NSInteger status = 0; // 默认值
  61. dispatch_sync(self.ioQueue, ^{
  62. NSNumber *statusNumber = self.statusCache[messageId];
  63. if (statusNumber) {
  64. status = [statusNumber integerValue];
  65. }
  66. });
  67. NSLog(@"getMessageStatusForMessageId 3: %ld", status);
  68. return status;
  69. }
  70. - (void)batchSaveMessageStatus:(NSDictionary<NSString *, NSNumber *> *)statusDict {
  71. if (!statusDict || statusDict.count == 0) {
  72. return;
  73. }
  74. dispatch_async(self.ioQueue, ^{
  75. // 批量更新内存缓存
  76. [self.statusCache addEntriesFromDictionary:statusDict];
  77. // 保存到文件
  78. [self saveCacheToDisk];
  79. NSLog(@"[MessageStatusManager] 批量保存成功: %lu 条", (unsigned long)statusDict.count);
  80. });
  81. }
  82. - (NSDictionary<NSString *, NSNumber *> *)batchGetMessageStatusForMessageIds:(NSArray<NSString *> *)messageIds {
  83. if (!messageIds || messageIds.count == 0) {
  84. return @{};
  85. }
  86. __block NSMutableDictionary *result = [NSMutableDictionary dictionary];
  87. dispatch_sync(self.ioQueue, ^{
  88. for (NSString *messageId in messageIds) {
  89. NSNumber *status = self.statusCache[messageId];
  90. if (status) {
  91. result[messageId] = status;
  92. } else {
  93. result[messageId] = @(1); // 默认发送成功
  94. }
  95. }
  96. });
  97. return [result copy];
  98. }
  99. - (void)removeMessageStatusForMessageId:(NSString *)messageId {
  100. if (!messageId || messageId.length == 0) {
  101. return;
  102. }
  103. dispatch_async(self.ioQueue, ^{
  104. [self.statusCache removeObjectForKey:messageId];
  105. // 保存到文件
  106. [self saveCacheToDisk];
  107. NSLog(@"[MessageStatusManager] 删除成功: messageId=%@", messageId);
  108. });
  109. }
  110. - (void)batchRemoveMessageStatusForMessageIds:(NSArray<NSString *> *)messageIds {
  111. if (!messageIds || messageIds.count == 0) {
  112. return;
  113. }
  114. dispatch_async(self.ioQueue, ^{
  115. [self.statusCache removeObjectsForKeys:messageIds];
  116. // 保存到文件
  117. [self saveCacheToDisk];
  118. NSLog(@"[MessageStatusManager] 批量删除成功: %lu 条", (unsigned long)messageIds.count);
  119. });
  120. }
  121. - (void)clearAllMessageStatus {
  122. dispatch_async(self.ioQueue, ^{
  123. [self.statusCache removeAllObjects];
  124. // 删除文件
  125. NSFileManager *fileManager = [NSFileManager defaultManager];
  126. if ([fileManager fileExistsAtPath:self.plistPath]) {
  127. NSError *error = nil;
  128. [fileManager removeItemAtPath:self.plistPath error:&error];
  129. if (error) {
  130. NSLog(@"[MessageStatusManager] 清空失败: %@", error);
  131. } else {
  132. NSLog(@"[MessageStatusManager] 清空成功");
  133. }
  134. }
  135. });
  136. }
  137. - (NSInteger)getAllMessageStatusCount {
  138. __block NSInteger count = 0;
  139. dispatch_sync(self.ioQueue, ^{
  140. count = self.statusCache.count;
  141. });
  142. return count;
  143. }
  144. #pragma mark - Private Methods
  145. /// 获取 plist 文件路径
  146. - (NSString *)plistFilePath {
  147. NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
  148. NSString *documentsDirectory = [paths firstObject];
  149. return [documentsDirectory stringByAppendingPathComponent:kMessageStatusPlistName];
  150. }
  151. /// 从磁盘加载缓存
  152. - (void)loadCache {
  153. dispatch_sync(self.ioQueue, ^{
  154. NSFileManager *fileManager = [NSFileManager defaultManager];
  155. if ([fileManager fileExistsAtPath:self.plistPath]) {
  156. NSDictionary *diskData = [NSDictionary dictionaryWithContentsOfFile:self.plistPath];
  157. if (diskData) {
  158. self.statusCache = [diskData mutableCopy];
  159. NSLog(@"[MessageStatusManager] 加载缓存成功: %lu 条", (unsigned long)self.statusCache.count);
  160. } else {
  161. self.statusCache = [NSMutableDictionary dictionary];
  162. NSLog(@"[MessageStatusManager] 缓存文件为空,创建新缓存");
  163. }
  164. } else {
  165. self.statusCache = [NSMutableDictionary dictionary];
  166. NSLog(@"[MessageStatusManager] 缓存文件不存在,创建新缓存");
  167. }
  168. });
  169. }
  170. /// 将缓存保存到磁盘
  171. - (void)saveCacheToDisk {
  172. // 注意: 此方法必须在 ioQueue 中调用
  173. BOOL success = [self.statusCache writeToFile:self.plistPath atomically:YES];
  174. if (!success) {
  175. NSLog(@"[MessageStatusManager] 保存到磁盘失败");
  176. }
  177. }
  178. @end