Files
keyboard/Shared/KBUserSessionManager.m
2025-12-04 21:53:47 +08:00

175 lines
5.3 KiB
Objective-C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// KBUserSessionManager.m
// keyBoard
//
// Created by Mac on 2025/12/1.
//
#import "KBUserSessionManager.h"
#import "KBAuthManager.h"
#import "KBUser.h"
#import "KBConfig.h"
#import <MJExtension/MJExtension.h>
#import "KBLoginVC.h"
/// App Group 里的用户缓存 key
static NSString * const kKBSessionUserStoreKey = @"KBSession.currentUser";
/// “本次安装是否已初始化”标记 key用来识别卸载重装
static NSString * const kKBSessionInstallFlagKey = @"KBSession.installInitialized";
@interface KBUserSessionManager ()
@property (nonatomic, strong) NSUserDefaults *defaults;
@property (atomic, strong, readwrite, nullable) KBUser *currentUser;
@property (nonatomic, assign) BOOL didBootstrap;
@end
@implementation KBUserSessionManager
+ (instancetype)shared {
static KBUserSessionManager *m;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
m = [KBUserSessionManager new];
});
return m;
}
- (instancetype)init {
if (self = [super init]) {
// 优先用 App Group 的 UserDefaultsApp 和扩展共用一份
NSUserDefaults *ud = [[NSUserDefaults alloc] initWithSuiteName:AppGroup];
_defaults = ud ?: [NSUserDefaults standardUserDefaults];
// 监听 token 变化(例如别处调用了 signOut
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(_onAuthChanged:)
name:KBAuthChangedNotification
object:nil];
}
return self;
}
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
#pragma mark - Public
- (void)bootstrapIfNeeded {
if (self.didBootstrap) return;
self.didBootstrap = YES;
// 使用本 App 的 standardUserDefaults 记录“本次安装是否已初始化”。
// 这样在卸载重装后,这个标记会被系统清空,从而触发一次性清理旧的 Keychain token。
NSUserDefaults *installDefaults = [NSUserDefaults standardUserDefaults];
BOOL hasInitializedThisInstall = [installDefaults boolForKey:kKBSessionInstallFlagKey];
KBAuthManager *auth = [KBAuthManager shared]; // 内部会 reloadFromKeychain
if (!hasInitializedThisInstall) {
// 说明是“卸载重装后的第一次运行”(或者真正第一次安装)
[installDefaults setBool:YES forKey:kKBSessionInstallFlagKey];
[installDefaults synchronize];
// 若此时 Keychain 里已有 token多半是上一次安装遗留的按你的需求清掉
if (auth.current.accessToken.length > 0) {
[auth signOut];
}
// 清除旧的用户缓存
[self.defaults removeObjectForKey:kKBSessionUserStoreKey];
[self.defaults synchronize];
self.currentUser = nil;
} else {
// 正常启动:从本地恢复用户信息
[self p_loadUserFromStore];
}
}
- (BOOL)isLoggedIn {
return [[KBAuthManager shared] isLoggedIn];
}
- (NSString *)accessToken {
return [KBAuthManager shared].current.accessToken;
}
- (void)handleLoginSuccessWithUser:(KBUser *)user {
if (!user) return;
// 先写 Keychain统一走 KBAuthManager
NSString *token = user.token;
if (token.length > 0) {
[[KBAuthManager shared] saveAccessToken:token
refreshToken:nil
expiryDate:nil
userIdentifier:nil];
}
// 再缓存用户信息,供 App/键盘使用
self.currentUser = user;
[self p_saveUserToStore:user];
}
- (void)logout {
// 清 Keychain
[[KBAuthManager shared] signOut];
// 清本地用户缓存
self.currentUser = nil;
[self.defaults removeObjectForKey:kKBSessionUserStoreKey];
[self.defaults synchronize];
}
#pragma mark - Private
- (void)p_loadUserFromStore {
id obj = [self.defaults objectForKey:kKBSessionUserStoreKey];
if (![obj isKindOfClass:[NSDictionary class]]) {
self.currentUser = nil;
return;
}
KBUser *user = [KBUser mj_objectWithKeyValues:(NSDictionary *)obj];
self.currentUser = user;
}
- (void)p_saveUserToStore:(KBUser *)user {
if (!user) {
[self.defaults removeObjectForKey:kKBSessionUserStoreKey];
[self.defaults synchronize];
return;
}
NSDictionary *dict = [user mj_keyValues];
if (dict) {
[self.defaults setObject:dict forKey:kKBSessionUserStoreKey];
[self.defaults synchronize];
}
}
- (void)_onAuthChanged:(NSNotification *)note {
// 避免在 KBAuthManager 的 +shared 初始化过程中再次调用 +shared 造成递归,
// 这里直接使用通知携带的实例。
KBAuthManager *auth = nil;
if ([note.object isKindOfClass:[KBAuthManager class]]) {
auth = (KBAuthManager *)note.object;
} else {
auth = [KBAuthManager shared];
}
// 如果 token 被别处清掉了,这里同步清一下 currentUser
if (![auth isLoggedIn]) {
self.currentUser = nil;
[self.defaults removeObjectForKey:kKBSessionUserStoreKey];
[self.defaults synchronize];
}
}
- (void)goLoginVC{
KBLoginVC *vc = [[KBLoginVC alloc] init];
UINavigationController *nav = KB_CURRENT_NAV;
if (nav) {
[nav pushViewController:vc animated:YES];
}
}
@end