// // KBFullAccessManager.m // // 统一封装“允许完全访问”检测: // 1) 首选:反射调用 UIInputViewController 的 hasFullAccess(避免直接引用私有 API 标识) // 2) 兜底:无法判断时返回 Unknown(上层可按需降级为 Denied 并提示) // #import "KBFullAccessManager.h" #import #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:"); ((void (*)(id, SEL, UIView *))objc_msgSend)(guideCls, sel, parent); } #endif return NO; } #pragma mark - Detect // 通过反射调用 hasFullAccess(若系统提供),否则返回 Unknown - (KBFullAccessState)p_detectFullAccessState { UIInputViewController *ivc = self.ivc; if (!ivc) return KBFullAccessStateUnknown; SEL sel = NSSelectorFromString(@"hasFullAccess"); if ([ivc respondsToSelector:sel]) { BOOL granted = ((BOOL (*)(id, SEL))objc_msgSend)(ivc, sel); return granted ? KBFullAccessStateGranted : KBFullAccessStateDenied; } // 无法判断时标记 Unknown(上层可按需处理为未开启) 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