处理ios18从其他app用自己键盘 拉起主app的bug
其他问题
This commit is contained in:
@@ -38,8 +38,10 @@
|
||||
#define KB_UL_BASE @"https://app.tknb.net/ul"
|
||||
#endif
|
||||
|
||||
#define KB_UL_LOGIN KB_UL_BASE @"/login"
|
||||
#define KB_UL_SETTINGS KB_UL_BASE @"/settings"
|
||||
#define KB_UL_LOGIN KB_UL_BASE @"/login"
|
||||
#define KB_UL_SETTINGS KB_UL_BASE @"/settings"
|
||||
// 充值入口的通用链接:当前复用 /login 路径,通过 query 区分(避免额外配置 AASA 路径)
|
||||
#define KB_UL_RECHARGE KB_UL_BASE @"/recharge"
|
||||
|
||||
#endif /* KBConfig_h */
|
||||
|
||||
|
||||
18
Shared/KBHostAppLauncher.h
Normal file
18
Shared/KBHostAppLauncher.h
Normal file
@@ -0,0 +1,18 @@
|
||||
//
|
||||
// KBHostAppLauncher.h
|
||||
// keyBoard
|
||||
//
|
||||
// Created by Mac on 2025/11/24.
|
||||
// 从扩展拉起主app
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface KBHostAppLauncher : NSObject
|
||||
/// 从某个 responder 出发,尝试通过 UIApplication 打开宿主 app 的 URL
|
||||
+ (BOOL)openHostAppURL:(NSURL *)url fromResponder:(UIResponder *)startResponder;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
52
Shared/KBHostAppLauncher.m
Normal file
52
Shared/KBHostAppLauncher.m
Normal file
@@ -0,0 +1,52 @@
|
||||
//
|
||||
// KBHostAppLauncher.m
|
||||
// keyBoard
|
||||
//
|
||||
// Created by Mac on 2025/11/24.
|
||||
//
|
||||
|
||||
// KBHostAppLauncher.m
|
||||
#import "KBHostAppLauncher.h"
|
||||
#import <objc/message.h>
|
||||
|
||||
@implementation KBHostAppLauncher
|
||||
|
||||
+ (BOOL)openHostAppURL:(NSURL *)url fromResponder:(UIResponder *)startResponder {
|
||||
if (!url || !startResponder) return NO;
|
||||
|
||||
UIResponder *responder = startResponder;
|
||||
while (responder) {
|
||||
if ([responder isKindOfClass:[UIApplication class]]) {
|
||||
UIApplication *app = (UIApplication *)responder;
|
||||
|
||||
if (@available(iOS 18.0, *)) {
|
||||
// iOS 18+:用新的 open:options:completionHandler:
|
||||
SEL sel = @selector(openURL:options:completionHandler:);
|
||||
if ([app respondsToSelector:sel]) {
|
||||
// 等价于 [app openURL:url options:@{} completionHandler:nil];
|
||||
void (*func)(id, SEL, NSURL *, NSDictionary *, void(^)(BOOL)) = (void *)objc_msgSend;
|
||||
if (func) {
|
||||
func(app, sel, url, @{}, nil);
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
return NO;
|
||||
} else {
|
||||
// iOS 17-:兼容老的 openURL:
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
if ([app respondsToSelector:@selector(openURL:)]) {
|
||||
return [app openURL:url];
|
||||
}
|
||||
#pragma clang diagnostic pop
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
responder = responder.nextResponder;
|
||||
}
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -25,6 +25,9 @@ typedef NS_ENUM(NSInteger, KBFARecord) {
|
||||
/// 最后一次由扩展上报的“完全访问”状态(来源:扩展运行后写入共享钥匙串)
|
||||
- (KBFARecord)lastKnownFullAccess;
|
||||
|
||||
/// 重置“完全访问”记录为 Unknown(删除共享钥匙串中的记录,用于 App 首次安装/升级时清理旧状态)
|
||||
- (void)resetFullAccessRecord;
|
||||
|
||||
/// 扩展侧:上报“完全访问”状态(写入共享钥匙串,以便 App 读取)
|
||||
- (void)reportFullAccessFromExtension:(BOOL)granted;
|
||||
|
||||
@@ -34,4 +37,3 @@ typedef NS_ENUM(NSInteger, KBFARecord) {
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ static NSString * const kKBPermAccount = @"full_access"; // 保存一个字节/
|
||||
#pragma mark - App side
|
||||
|
||||
- (BOOL)isKeyboardEnabled {
|
||||
// 与 AppDelegate 中同思路:遍历 activeInputModes,匹配自家扩展 bundle id
|
||||
// 与 AppDelegate 中同思路:遍历 activeInputModes,匹配自家扩展 bundle id 方法2:网上看也有判断Bundle拿到keyboards的方法
|
||||
for (UITextInputMode *mode in [UITextInputMode activeInputModes]) {
|
||||
NSString *identifier = nil;
|
||||
@try { identifier = [mode valueForKey:@"identifier"]; } @catch (__unused NSException *e) { identifier = nil; }
|
||||
@@ -63,6 +63,14 @@ static NSString * const kKBPermAccount = @"full_access"; // 保存一个字节/
|
||||
[self keychainWrite:data];
|
||||
}
|
||||
|
||||
#pragma mark - Reset
|
||||
|
||||
- (void)resetFullAccessRecord {
|
||||
// 删除共享钥匙串中的记录,让 lastKnownFullAccess 回退为 Unknown
|
||||
NSMutableDictionary *query = [self baseKCQuery];
|
||||
SecItemDelete((__bridge CFDictionaryRef)query);
|
||||
}
|
||||
|
||||
#pragma mark - Keychain shared blob
|
||||
|
||||
- (NSMutableDictionary *)baseKCQuery {
|
||||
|
||||
@@ -116,6 +116,13 @@
|
||||
"Apply failed" = "Apply failed";
|
||||
"Open agreement" = "Open agreement";
|
||||
"Shop Mall" = "Shop Mall";
|
||||
"My skin" = "My skin";
|
||||
"my_skin_selected_count" = "Selected: %ld Skins";
|
||||
"Editor" = "Editor";
|
||||
"Cancel" = "Cancel";
|
||||
"Delete" = "Delete";
|
||||
|
||||
|
||||
|
||||
// Skin sample names
|
||||
"极光" = "Aurora";
|
||||
|
||||
@@ -117,6 +117,11 @@
|
||||
"Apply failed" = "应用失败";
|
||||
"Open agreement" = "跳转协议";
|
||||
"Shop Mall" = "购物商城";
|
||||
"My skin" = "我的皮肤";
|
||||
"my_skin_selected_count" = "已选择:%ld 个皮肤";
|
||||
"Editor" = "编辑";
|
||||
"Cancel" = "取消";
|
||||
"Delete" = "删除";
|
||||
|
||||
// 皮肤示例名称
|
||||
"极光" = "极光";
|
||||
|
||||
Reference in New Issue
Block a user