From edf88721da3f75e3d288b68d4c8009d8e186ed9f Mon Sep 17 00:00:00 2001 From: CodeST <694468528@qq.com> Date: Mon, 3 Nov 2025 18:45:06 +0800 Subject: [PATCH] =?UTF-8?q?=E8=B0=83=E6=95=B4=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Shared/KBConfig.h | 6 +++ keyBoard.xcodeproj/project.pbxproj | 10 ++--- .../back_black_icon.imageset/Contents.json | 22 +++++++++ .../back_black_icon.imageset/back@2x.png | Bin 0 -> 388 bytes .../back_black_icon.imageset/back@3x.png | Bin 0 -> 674 bytes .../{Main => Base}/VC/BaseTabBarController.h | 0 .../{Main => Base}/VC/BaseTabBarController.m | 0 keyBoard/Class/Guard/VC/KBGuideVC.m | 42 +++++++++++------- keyBoard/VC/KBPermissionViewController.h | 3 +- keyBoard/VC/KBPermissionViewController.m | 27 ++++++++--- 10 files changed, 82 insertions(+), 28 deletions(-) create mode 100644 keyBoard/Assets.xcassets/back_black_icon.imageset/Contents.json create mode 100644 keyBoard/Assets.xcassets/back_black_icon.imageset/back@2x.png create mode 100644 keyBoard/Assets.xcassets/back_black_icon.imageset/back@3x.png rename keyBoard/Class/{Main => Base}/VC/BaseTabBarController.h (100%) rename keyBoard/Class/{Main => Base}/VC/BaseTabBarController.m (100%) diff --git a/Shared/KBConfig.h b/Shared/KBConfig.h index 46ab8b2..f98849a 100644 --- a/Shared/KBConfig.h +++ b/Shared/KBConfig.h @@ -36,3 +36,9 @@ #ifndef KB_KEYBOARD_EXTENSION_BUNDLE_ID #define KB_KEYBOARD_EXTENSION_BUNDLE_ID @"com.keyBoardst.CustomKeyboard" #endif + +// --- 常用宏 --- +// 弱引用 self(在 block 中避免循环引用):使用处直接写 KBWeakSelf; +#ifndef KBWeakSelf +#define KBWeakSelf __weak __typeof(self) weakSelf = self; +#endif diff --git a/keyBoard.xcodeproj/project.pbxproj b/keyBoard.xcodeproj/project.pbxproj index 1e31e13..556c9fa 100644 --- a/keyBoard.xcodeproj/project.pbxproj +++ b/keyBoard.xcodeproj/project.pbxproj @@ -38,7 +38,6 @@ 04FC95D22EB1E7AE007BD342 /* MyVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC95D12EB1E7AE007BD342 /* MyVC.m */; }; 04FC95D72EB1EA16007BD342 /* BaseTableView.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC95D62EB1EA16007BD342 /* BaseTableView.m */; }; 04FC95D82EB1EA16007BD342 /* BaseCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC95D42EB1EA16007BD342 /* BaseCell.m */; }; - A1B2D7022EB8C00100000001 /* KBLangTestVC.m in Sources */ = {isa = PBXBuildFile; fileRef = A1B2D7012EB8C00100000001 /* KBLangTestVC.m */; }; 04FC95DD2EB202A3007BD342 /* KBGuideVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC95DC2EB202A3007BD342 /* KBGuideVC.m */; }; 04FC95E52EB220B5007BD342 /* UIColor+Extension.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC95E42EB220B5007BD342 /* UIColor+Extension.m */; }; 04FC95E92EB23B67007BD342 /* KBNetworkManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC95E72EB23B67007BD342 /* KBNetworkManager.m */; }; @@ -59,6 +58,7 @@ A1B2C4002EB4A0A100000004 /* KBAuthManager.m in Sources */ = {isa = PBXBuildFile; fileRef = A1B2C4002EB4A0A100000002 /* KBAuthManager.m */; }; A1B2C4202EB4B7A100000001 /* KBKeyboardPermissionManager.m in Sources */ = {isa = PBXBuildFile; fileRef = A1B2C4222EB4B7A100000001 /* KBKeyboardPermissionManager.m */; }; A1B2C4212EB4B7A100000001 /* KBKeyboardPermissionManager.m in Sources */ = {isa = PBXBuildFile; fileRef = A1B2C4222EB4B7A100000001 /* KBKeyboardPermissionManager.m */; }; + A1B2D7022EB8C00100000001 /* KBLangTestVC.m in Sources */ = {isa = PBXBuildFile; fileRef = A1B2D7012EB8C00100000001 /* KBLangTestVC.m */; }; ECC9EE02174D86E8D792472F /* Pods_keyBoard.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 967065BB5230E43F293B3AF9 /* Pods_keyBoard.framework */; }; /* End PBXBuildFile section */ @@ -136,8 +136,6 @@ 04FC95CB2EB1E780007BD342 /* BaseTabBarController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BaseTabBarController.m; sourceTree = ""; }; 04FC95CD2EB1E7A1007BD342 /* HomeVC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HomeVC.h; sourceTree = ""; }; 04FC95CE2EB1E7A1007BD342 /* HomeVC.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HomeVC.m; sourceTree = ""; }; - A1B2D7002EB8C00100000001 /* KBLangTestVC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBLangTestVC.h; sourceTree = ""; }; - A1B2D7012EB8C00100000001 /* KBLangTestVC.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBLangTestVC.m; sourceTree = ""; }; 04FC95D02EB1E7AE007BD342 /* MyVC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MyVC.h; sourceTree = ""; }; 04FC95D12EB1E7AE007BD342 /* MyVC.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MyVC.m; sourceTree = ""; }; 04FC95D32EB1EA16007BD342 /* BaseCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BaseCell.h; sourceTree = ""; }; @@ -184,6 +182,8 @@ A1B2C4002EB4A0A100000002 /* KBAuthManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBAuthManager.m; sourceTree = ""; }; A1B2C4222EB4B7A100000001 /* KBKeyboardPermissionManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBKeyboardPermissionManager.m; sourceTree = ""; }; A1B2C4232EB4B7A100000001 /* KBKeyboardPermissionManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBKeyboardPermissionManager.h; sourceTree = ""; }; + A1B2D7002EB8C00100000001 /* KBLangTestVC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBLangTestVC.h; sourceTree = ""; }; + A1B2D7012EB8C00100000001 /* KBLangTestVC.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBLangTestVC.m; sourceTree = ""; }; B12EC429812407B9F0E67565 /* Pods-CustomKeyboard.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-CustomKeyboard.release.xcconfig"; path = "Target Support Files/Pods-CustomKeyboard/Pods-CustomKeyboard.release.xcconfig"; sourceTree = ""; }; B8CA018AB878499327504AAD /* Pods-CustomKeyboard.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-CustomKeyboard.debug.xcconfig"; path = "Target Support Files/Pods-CustomKeyboard/Pods-CustomKeyboard.debug.xcconfig"; sourceTree = ""; }; F67DDBD716E4E616D8CC2C9C /* Pods-keyBoard.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-keyBoard.debug.xcconfig"; path = "Target Support Files/Pods-keyBoard/Pods-keyBoard.debug.xcconfig"; sourceTree = ""; }; @@ -358,8 +358,6 @@ 04FC95B92EB1E3B1007BD342 /* VC */ = { isa = PBXGroup; children = ( - 04FC95CA2EB1E780007BD342 /* BaseTabBarController.h */, - 04FC95CB2EB1E780007BD342 /* BaseTabBarController.m */, ); path = VC; sourceTree = ""; @@ -446,6 +444,8 @@ children = ( 04FC95C72EB1E4C9007BD342 /* BaseNavigationController.h */, 04FC95C82EB1E4C9007BD342 /* BaseNavigationController.m */, + 04FC95CA2EB1E780007BD342 /* BaseTabBarController.h */, + 04FC95CB2EB1E780007BD342 /* BaseTabBarController.m */, ); path = VC; sourceTree = ""; diff --git a/keyBoard/Assets.xcassets/back_black_icon.imageset/Contents.json b/keyBoard/Assets.xcassets/back_black_icon.imageset/Contents.json new file mode 100644 index 0000000..79099b2 --- /dev/null +++ b/keyBoard/Assets.xcassets/back_black_icon.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "back@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "back@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/keyBoard/Assets.xcassets/back_black_icon.imageset/back@2x.png b/keyBoard/Assets.xcassets/back_black_icon.imageset/back@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..a41e24cac3b0d7d729777b858aae7dc970750557 GIT binary patch literal 388 zcmV-~0ek+5P)Px$K1oDDR9HvF*Re_jF%W>^2`sEHuy8B{w-9W6gtM@-xZ)nd2e7fT(8A8f2e7`< z%HGyDP{bz5hJ&@=X0xNQI*!}hY%-&Hf&YVn86x1HpWx~jMKR0s{LmQly05_kD9iFV z%d!^$m;u10QtDv{K@Ql8|8|{oi@L6#cOggtyW&3D_x*)2=8+XJ6#t3dD5Y*$M-UtL zsN@l(#FGK3@gx96JQ_e1j{;D}Cj+SClK>p?U;tM<2*4Q+0!S%8gb+uYs}vFMwboY@ zr+jo1N-3X&5X-IDTidp0P1CGX5u<>rst%lU9&yfr7zOw!Cn5;Ii3kR8AtnJh5R(Da zh$sLhA{s!2NCHqGk^!j*62KUu>$+2G?HB96U>^bzueH{9?0^Bp8WHDO>(4&{Y#>$u iaN_@k*4p=>tN9IoK?g7ZN>Pje0000Px%TuDShRA@uhnZIk>KorN{JCS(pR8Qv{>PeJN9g->ORw%U1|4>5d+`T`bbEizD zkiQ_LQ?~wqLINF2$71;`8)^?N*uln?bm71Tw_tZJO#GAPmFJ@p$|t2!bsgJV}x#aU8!d3gH!?*=*iyG#bZ< zxUH1Zne~s(^i)du4gfL}h%W#P!*F9VnS2I-?VOP3K@i;PbUMFk39!_LF}Ahn{69Gn z5tLH5rIbHv2auypUdESF$~XFxs1txm8(@q1#qDa8GtKoC;*&lQ#pWZZ7K!up-oi)-n6L% zz^68)0eovy3ZUI?H|F#Cr%QHHYb}Y3E}iqnS+9kJ5GMd|KW`_sDDXl``MOLfo4M8i ztyb$d0Nl8w$hlJLUa!~tW)q^!SZe^z`9nnfa7EF1nx;Gbe*dgYu%dIV0rZ18=g$!F zEdXrh6w-f<{6)mwZnt|{G|0N+)&f|8IJlzl5D_0!L#z#;g9{<{lu}1Nbt(l=2c1d- z_|~Zs0G~Ql2H;DlN&$T6R5^faok##&>O= *items; // 数据源 [{type, text}] +/// 权限引导页作为子控制器(用于“同时隐藏”) +@property (nonatomic, strong, nullable) KBPermissionViewController *permVC; @end @@ -80,6 +82,9 @@ typedef NS_ENUM(NSInteger, KBGuideItemType) { // 监听应用回到前台/变为活跃:用于从设置返回时再次校验权限 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(kb_checkKeyboardPermission) name:UIApplicationDidBecomeActiveNotification object:nil]; + + // 提前创建并铺满权限引导页(默认隐藏),避免后续显示时出现布局进场感 + [self kb_preparePermissionOverlayIfNeeded]; } - (void)dealloc { @@ -101,23 +106,26 @@ typedef NS_ENUM(NSInteger, KBGuideItemType) { KBFARecord fa = [mgr lastKnownFullAccess]; BOOL needGuide = (!enabled) || (enabled && fa == KBFARecordDenied); - UIViewController *top = [UIViewController kb_topMostViewController]; - if (needGuide) { - if (![top isKindOfClass:[KBPermissionViewController class]]) { - KBPermissionViewController *guide = [KBPermissionViewController new]; - guide.modalPresentationStyle = UIModalPresentationFullScreen; - __weak typeof(self) weakSelf = self; - guide.onBack = ^{ - // 用户主动点击“返回”时,同步退出引导页 - [weakSelf.navigationController popViewControllerAnimated:YES]; - }; - [top presentViewController:guide animated:YES completion:nil]; - } - } else { - if ([top isKindOfClass:[KBPermissionViewController class]]) { - [top dismissViewControllerAnimated:YES completion:nil]; - } - } + [self kb_preparePermissionOverlayIfNeeded]; + BOOL show = needGuide; + [UIView performWithoutAnimation:^{ + self.permVC.view.hidden = !show; + }]; +} + +/// 提前创建权限引导页覆盖层(仅一次) +- (void)kb_preparePermissionOverlayIfNeeded { + if (self.permVC) return; + KBPermissionViewController *guide = [KBPermissionViewController new]; + guide.modalPresentationStyle = UIModalPresentationFullScreen; // 仅用于内部布局,不会真正 present + KBWeakSelf; + guide.backHandler = ^{ [weakSelf.navigationController popViewControllerAnimated:YES]; }; + self.permVC = guide; + [self addChildViewController:guide]; + [self.view addSubview:guide.view]; + [guide.view mas_makeConstraints:^(MASConstraintMaker *make) { make.edges.equalTo(self.view); }]; + [guide didMoveToParentViewController:self]; + guide.view.hidden = YES; // 初始隐藏 } - (void)kb_didTapBackground { diff --git a/keyBoard/VC/KBPermissionViewController.h b/keyBoard/VC/KBPermissionViewController.h index c425135..d3d91e0 100644 --- a/keyBoard/VC/KBPermissionViewController.h +++ b/keyBoard/VC/KBPermissionViewController.h @@ -12,7 +12,8 @@ NS_ASSUME_NONNULL_BEGIN @interface KBPermissionViewController : UIViewController /// 点击页面左上角“返回”时回调。用于让调用方(如 KBGuideVC)一起退出等自定义行为。 -@property (nonatomic, copy, nullable) void (^onBack)(void); +/// 注意:避免与按钮 action `onBack` 重名,故命名为 backHandler。 +@property (nonatomic, copy, nullable) void (^backHandler)(void); @end diff --git a/keyBoard/VC/KBPermissionViewController.m b/keyBoard/VC/KBPermissionViewController.m index aec5744..dc1bb40 100644 --- a/keyBoard/VC/KBPermissionViewController.m +++ b/keyBoard/VC/KBPermissionViewController.m @@ -78,11 +78,28 @@ #pragma mark - Actions - (void)onBack { - // 先关闭自身,再让调用方按需处理(例如同时退出引导页) - void (^handler)(void) = self.onBack; - [self dismissViewControllerAnimated:YES completion:^{ - if (handler) handler(); - }]; + // 支持两种展示方式: + // 1) 作为子控制器嵌入(无 presentingViewController)→ 交由回调让父 VC 处理(通常 pop) + // 2) 作为模态弹出 → 按原策略先 pop 再 dismiss + UIViewController *presenter = self.presentingViewController; + if (!presenter) { + if (self.backHandler) self.backHandler(); + return; + } + + UINavigationController *nav = nil; + if ([presenter isKindOfClass:UINavigationController.class]) { + nav = (UINavigationController *)presenter; + } else if (presenter.navigationController) { + nav = presenter.navigationController; + } + + if (nav) { + [nav popViewControllerAnimated:NO]; + [nav dismissViewControllerAnimated:YES completion:^{ if (self.backHandler) self.backHandler(); }]; + } else { + [self dismissViewControllerAnimated:YES completion:^{ if (self.backHandler) self.backHandler(); }]; + } } - (void)openSettings {