// // KBFullAccessManager.m // // 统一封装“允许完全访问”检测: // 1) 直接使用 UIInputViewController.hasFullAccess(公开 API) // 2) 兜底:无法判断时返回 Unknown(上层可按需降级为 Denied 并提示) // #import "KBFullAccessManager.h" #if __has_include("KBNetworkManager.h") #import "KBNetworkManager.h" #endif #if __has_include("KBKeyboardPermissionManager.h") #import "KBKeyboardPermissionManager.h" #endif NSNotificationName const KBFullAccessChangedNotification = @"KBFullAccessChangedNotification"; @interface KBFullAccessManager () @property (nonatomic, weak) UIInputViewController *ivc; @property (nonatomic, assign) KBFullAccessState state; @end @implementation KBFullAccessManager + (instancetype)shared { static KBFullAccessManager *m; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ m = [KBFullAccessManager new]; }); return m; } - (instancetype)init { if (self = [super init]) { _state = KBFullAccessStateUnknown; } return self; } - (void)bindInputController:(UIInputViewController *)ivc { self.ivc = ivc; [self refresh]; } - (KBFullAccessState)currentState { return _state; } - (BOOL)hasFullAccess { return self.state == KBFullAccessStateGranted; } - (void)refresh { KBFullAccessState newState = [self p_detectFullAccessState]; if (newState != self.state) { self.state = newState; [[NSNotificationCenter defaultCenter] postNotificationName:KBFullAccessChangedNotification object:nil]; [self p_applySideEffects]; } } - (BOOL)ensureFullAccessOrGuideInView:(UIView *)parent { [self refresh]; if (self.state == KBFullAccessStateGranted) return YES; #if __has_include("KBFullAccessGuideView.h") // 动态引入,避免主 App 编译引用 Class guideCls = NSClassFromString(@"KBFullAccessGuideView"); if (guideCls && [guideCls respondsToSelector:NSSelectorFromString(@"showInView:")]) { SEL sel = NSSelectorFromString(@"showInView:"); #pragma clang diagnostic push #pragma clang diagnostic ignored "-Warc-performSelector-leaks" [guideCls performSelector:sel withObject:parent]; #pragma clang diagnostic pop } #endif return NO; } #pragma mark - Detect // 通过反射调用 hasFullAccess(若系统提供),否则返回 Unknown - (KBFullAccessState)p_detectFullAccessState { UIInputViewController *ivc = self.ivc; if (!ivc) return KBFullAccessStateUnknown; if ([ivc respondsToSelector:@selector(hasFullAccess)]) { return ivc.hasFullAccess ? KBFullAccessStateGranted : KBFullAccessStateDenied; } return KBFullAccessStateUnknown; } #pragma mark - Side Effects - (void)p_applySideEffects { #if __has_include("KBNetworkManager.h") // 根据完全访问状态切换网络总开关 [KBNetworkManager shared].enabled = (self.state == KBFullAccessStateGranted); #endif #if __has_include("KBKeyboardPermissionManager.h") // 上报给主 App:记录最近一次“完全访问”状态(App 将据此决定是否展示引导页) [[KBKeyboardPermissionManager shared] reportFullAccessFromExtension:(self.state == KBFullAccessStateGranted)]; #endif } @end