This commit is contained in:
2025-11-04 16:37:24 +08:00
parent 6fb9e56720
commit 3e2dc4bcb6
6 changed files with 92 additions and 26 deletions

View File

@@ -5,6 +5,7 @@
#import "KBFullAccessGuideView.h"
#import "Masonry.h"
#import "KBResponderUtils.h" // UIInputViewController
@interface KBFullAccessGuideView ()
@property (nonatomic, strong) UIControl *backdrop;
@@ -146,21 +147,12 @@
#pragma mark - Actions
- (UIInputViewController *)kb_findInputController {
UIResponder *res = self;
while (res) {
if ([res isKindOfClass:[UIInputViewController class]]) {
return (UIInputViewController *)res;
}
res = res.nextResponder;
}
return nil;
}
// KBResponderUtils.h
- (void)onTapGoEnable {
// 使 UIApplication宿
// App App 宿
UIInputViewController *ivc = [self kb_findInputController];
UIInputViewController *ivc = KBFindInputViewController(self);
if (!ivc) { [self dismiss]; return; }
// Universal Link scheme

View File

@@ -6,6 +6,7 @@
//
#import "KBFunctionView.h"
#import "KBResponderUtils.h" // UIInputViewController
#import "KBFunctionBarView.h"
#import "KBFunctionPasteView.h"
#import "KBFunctionTagCell.h"
@@ -169,7 +170,7 @@ static NSString * const kKBFunctionTagCellId = @"KBFunctionTagCellId";
[KBHUD showInfo:@"处理中…"];
// return;
UIInputViewController *ivc = [self findInputViewController];
UIInputViewController *ivc = KBFindInputViewController(self);
if (!ivc) return;
NSString *title = (indexPath.item < self.itemsInternal.count) ? self.itemsInternal[indexPath.item] : @"";
@@ -268,14 +269,14 @@ static NSString * const kKBFunctionTagCellId = @"KBFunctionTagCellId";
}
- (void)onTapDelete {
NSLog(@"点击:删除");
UIInputViewController *ivc = [self findInputViewController];
UIInputViewController *ivc = KBFindInputViewController(self);
id<UITextDocumentProxy> proxy = ivc.textDocumentProxy;
[proxy deleteBackward];
}
- (void)onTapClear {
NSLog(@"点击:清空");
// pasteView
UIInputViewController *ivc = [self findInputViewController];
UIInputViewController *ivc = KBFindInputViewController(self);
id<UITextDocumentProxy> proxy = ivc.textDocumentProxy;
// documentContextBeforeInput 50
NSInteger guard = 0; //
@@ -292,7 +293,7 @@ static NSString * const kKBFunctionTagCellId = @"KBFunctionTagCellId";
- (void)onTapSend {
NSLog(@"点击:发送");
// App
UIInputViewController *ivc = [self findInputViewController];
UIInputViewController *ivc = KBFindInputViewController(self);
id<UITextDocumentProxy> proxy = ivc.textDocumentProxy;
[proxy insertText:@"\n"];
}
@@ -417,16 +418,6 @@ static NSString * const kKBFunctionTagCellId = @"KBFunctionTagCellId";
#pragma mark - Find Owner Controller
// 宿 UIInputViewControllerKeyboardViewController
- (UIInputViewController *)findInputViewController {
UIResponder *responder = self;
while (responder) {
if ([responder isKindOfClass:[UIInputViewController class]]) {
return (UIInputViewController *)responder;
}
responder = responder.nextResponder;
}
return nil;
}
// KBResponderUtils.h
@end

View File

@@ -6,6 +6,7 @@
#import "KBKeyboardView.h"
#import "KBKeyButton.h"
#import "KBKey.h"
#import "KBResponderUtils.h" //
@interface KBKeyboardView ()
@property (nonatomic, strong) UIView *row1;
@@ -13,6 +14,8 @@
@property (nonatomic, strong) UIView *row3;
@property (nonatomic, strong) UIView *row4;
@property (nonatomic, strong) NSArray<NSArray<KBKey *> *> *keysForRows;
// 退使 NSTimer GCD
@property (nonatomic, assign) BOOL backspaceHoldActive;
@end
@implementation KBKeyboardView
@@ -196,6 +199,16 @@
[btn addTarget:self action:@selector(onKeyTapped:) forControlEvents:UIControlEventTouchUpInside];
[row addSubview:btn];
// NSTimer使 UILongPressGestureRecognizer
// 1
if (key.type == KBKeyTypeBackspace) {
UILongPressGestureRecognizer *lp = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(onBackspaceLongPress:)];
// 0.5s
lp.minimumPressDuration = 0.35;
lp.cancelsTouchesInView = YES; //
[btn addGestureRecognizer:lp];
}
// Shift
if (key.type == KBKeyTypeShift) {
btn.selected = self.shiftOn;
@@ -293,6 +306,42 @@
}
}
// 退使 NSTimer/DisplayLink
- (void)onBackspaceLongPress:(UILongPressGestureRecognizer *)gr {
switch (gr.state) {
case UIGestureRecognizerStateBegan: {
self.backspaceHoldActive = YES;
[self kb_backspaceStep];
} break;
case UIGestureRecognizerStateEnded:
case UIGestureRecognizerStateCancelled:
case UIGestureRecognizerStateFailed: {
self.backspaceHoldActive = NO;
} break;
default: break;
}
}
#pragma mark - Helpers
//
- (void)kb_backspaceStep {
if (!self.backspaceHoldActive) { return; }
UIInputViewController *ivc = KBFindInputViewController(self);
if (!ivc) { self.backspaceHoldActive = NO; return; }
id<UITextDocumentProxy> proxy = ivc.textDocumentProxy;
NSString *before = proxy.documentContextBeforeInput ?: @"";
if (before.length <= 0) { self.backspaceHoldActive = NO; return; }
[proxy deleteBackward]; // 1
// 使 NSTimer
__weak typeof(self) weakSelf = self;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.06 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
__strong typeof(weakSelf) selfStrong = weakSelf;
[selfStrong kb_backspaceStep];
});
}
#pragma mark - Lazy
- (UIView *)row1 { if (!_row1) _row1 = [UIView new]; return _row1; }

View File

@@ -0,0 +1,28 @@
//
// KBResponderUtils.h
// CustomKeyboard
//
// 统一封装:从任意 UIView/UIResponder 起,向响应链上查找 UIInputViewController。
// 作为 headeronly 的工具,便于多处直接引入使用。
//
#import <UIKit/UIKit.h>
#ifndef KBResponderUtils_h
#define KBResponderUtils_h
/// 从给定 responder 开始,沿响应链查找宿主 UIInputViewController。
/// 用法UIInputViewController *ivc = KBFindInputViewController(self);
static inline UIInputViewController *KBFindInputViewController(UIResponder *start) {
UIResponder *responder = start;
while (responder) {
if ([responder isKindOfClass:[UIInputViewController class]]) {
return (UIInputViewController *)responder;
}
responder = responder.nextResponder;
}
return nil;
}
#endif /* KBResponderUtils_h */