From b23927968fa08780adc1956ab5374fea4f55d2b2 Mon Sep 17 00:00:00 2001 From: CodeST <694468528@qq.com> Date: Thu, 20 Nov 2025 15:35:22 +0800 Subject: [PATCH] 2 --- Shared/KBSkinManager.m | 83 +++++++++++++++++++++--------------------- 1 file changed, 41 insertions(+), 42 deletions(-) diff --git a/Shared/KBSkinManager.m b/Shared/KBSkinManager.m index 6f2040f..d024170 100644 --- a/Shared/KBSkinManager.m +++ b/Shared/KBSkinManager.m @@ -3,14 +3,13 @@ // #import "KBSkinManager.h" -#import #import "KBConfig.h" NSString * const KBSkinDidChangeNotification = @"KBSkinDidChangeNotification"; NSString * const KBDarwinSkinChanged = @"com.loveKey.nyx.skin.changed"; -static NSString * const kKBSkinService = @"com.loveKey.nyx.skin"; // Keychain service -static NSString * const kKBSkinAccount = @"current"; // Keychain account +// 使用 App Group 里的 NSUserDefaults 持久化皮肤主题(不再依赖 Keychain)。 +static NSString * const kKBSkinThemeStoreKey = @"KBSkinThemeCurrent"; @implementation KBSkinTheme @@ -81,8 +80,8 @@ static NSString * const kKBSkinAccount = @"current"; // Keychain ac - (instancetype)init { if (self = [super init]) { - KBSkinTheme *t = [self p_loadFromKeychain]; - // 若 Keychain 中的皮肤在 App Group 中找不到对应资源目录(如首次安装 / 已被清理),则回退到默认皮肤。 + KBSkinTheme *t = [self p_loadFromStore]; + // 若存储中的皮肤在 App Group 中找不到对应资源目录(如首次安装 / 已被清理),则回退到默认皮肤。 if (!t || ![self.class kb_hasAssetsForSkinId:t.skinId]) { t = [self.class defaultTheme]; } @@ -100,7 +99,7 @@ static NSString * const kKBSkinAccount = @"current"; // Keychain ac static void KBSkinDarwinCallback(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo) { KBSkinManager *self = (__bridge KBSkinManager *)observer; - [self p_reloadFromKeychainAndBroadcast:YES]; + [self p_reloadFromStoreAndBroadcast:YES]; } - (void)dealloc { @@ -134,13 +133,17 @@ static void KBSkinDarwinCallback(CFNotificationCenterRef center, void *observer, - (BOOL)applyTheme:(KBSkinTheme *)theme { if (!theme) return NO; - if ([self p_saveToKeychain:theme]) { - self.current = theme; - [[NSNotificationCenter defaultCenter] postNotificationName:KBSkinDidChangeNotification object:nil]; - CFNotificationCenterPostNotification(CFNotificationCenterGetDarwinNotifyCenter(), (__bridge CFStringRef)KBDarwinSkinChanged, NULL, NULL, true); - return YES; - } - return NO; + // 将主题写入 App Group 存储(失败也不影响本次进程内的使用) + [self p_saveToStore:theme]; + // 始终更新当前主题并广播通知,确保当前进程和扩展之间保持同步。 + self.current = theme; + [[NSNotificationCenter defaultCenter] postNotificationName:KBSkinDidChangeNotification object:nil]; + CFNotificationCenterPostNotification(CFNotificationCenterGetDarwinNotifyCenter(), + (__bridge CFStringRef)KBDarwinSkinChanged, + NULL, + NULL, + true); + return YES; } - (void)resetToDefault { @@ -329,44 +332,40 @@ static void KBSkinDarwinCallback(CFNotificationCenterRef center, void *observer, return t; } -#pragma mark - Keychain +#pragma mark - Persistence (App Group) -- (NSMutableDictionary *)baseKCQuery { - NSMutableDictionary *q = [@{ (__bridge id)kSecClass: (__bridge id)kSecClassGenericPassword, - (__bridge id)kSecAttrService: kKBSkinService, - (__bridge id)kSecAttrAccount: kKBSkinAccount } mutableCopy]; - q[(__bridge id)kSecAttrAccessGroup] = KB_KEYCHAIN_ACCESS_GROUP; - return q; -} - -- (BOOL)p_saveToKeychain:(KBSkinTheme *)theme { +/// 将当前皮肤主题写入 App Group 对应的 NSUserDefaults。 +- (BOOL)p_saveToStore:(KBSkinTheme *)theme { + if (!theme) return NO; NSError *err = nil; - NSData *data = [NSKeyedArchiver archivedDataWithRootObject:theme requiringSecureCoding:YES error:&err]; + NSData *data = [NSKeyedArchiver archivedDataWithRootObject:theme + requiringSecureCoding:YES + error:&err]; if (err || data.length == 0) return NO; - NSMutableDictionary *q = [self baseKCQuery]; - SecItemDelete((__bridge CFDictionaryRef)q); - q[(__bridge id)kSecValueData] = data; - q[(__bridge id)kSecAttrAccessible] = (__bridge id)kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly; - OSStatus st = SecItemAdd((__bridge CFDictionaryRef)q, NULL); - return (st == errSecSuccess); + NSUserDefaults *ud = [[NSUserDefaults alloc] initWithSuiteName:AppGroup]; + if (!ud) return NO; + [ud setObject:data forKey:kKBSkinThemeStoreKey]; + return [ud synchronize]; } -- (KBSkinTheme *)p_loadFromKeychain { - NSMutableDictionary *q = [self baseKCQuery]; - q[(__bridge id)kSecReturnData] = @YES; - q[(__bridge id)kSecMatchLimit] = (__bridge id)kSecMatchLimitOne; - CFTypeRef dataRef = NULL; OSStatus st = SecItemCopyMatching((__bridge CFDictionaryRef)q, &dataRef); - if (st != errSecSuccess || !dataRef) return nil; - NSData *data = (__bridge_transfer NSData *)dataRef; - if (data.length == 0) return nil; +/// 从 App Group 的 NSUserDefaults 读取已存主题。 +- (KBSkinTheme *)p_loadFromStore { + NSUserDefaults *ud = [[NSUserDefaults alloc] initWithSuiteName:AppGroup]; + if (!ud) return nil; + NSData *data = [ud objectForKey:kKBSkinThemeStoreKey]; + if (![data isKindOfClass:NSData.class] || data.length == 0) return nil; @try { - KBSkinTheme *t = [NSKeyedUnarchiver unarchivedObjectOfClass:KBSkinTheme.class fromData:data error:NULL]; + KBSkinTheme *t = [NSKeyedUnarchiver unarchivedObjectOfClass:KBSkinTheme.class + fromData:data + error:NULL]; return t; - } @catch (__unused NSException *e) { return nil; } + } @catch (__unused NSException *e) { + return nil; + } } -- (void)p_reloadFromKeychainAndBroadcast:(BOOL)broadcast { - KBSkinTheme *t = [self p_loadFromKeychain]; +- (void)p_reloadFromStoreAndBroadcast:(BOOL)broadcast { + KBSkinTheme *t = [self p_loadFromStore]; if (!t || ![self.class kb_hasAssetsForSkinId:t.skinId]) { t = [self.class defaultTheme]; }