You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何获取iOS虚拟键盘按键按下/抬起的时间戳?

可行解决方案

方案一:Hook UIWindow的sendEvent:方法(推荐)

系统所有触摸事件(包括虚拟键盘按键的触摸)都会经过UIWindow的sendEvent:方法,通过Method Swizzling替换该方法,可直接捕获虚拟键盘按键的按下/抬起事件:

  1. 实现Method Swizzling替换逻辑
#import <objc/runtime.h>

@implementation UIWindow (KeyEventHook)

+ (void)load {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        Class class = [self class];
        SEL originalSelector = @selector(sendEvent:);
        SEL swizzledSelector = @selector(custom_sendEvent:);
        
        Method originalMethod = class_getInstanceMethod(class, originalSelector);
        Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);
        
        BOOL didAddMethod = class_addMethod(class, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod));
        if (didAddMethod) {
            class_replaceMethod(class, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));
        } else {
            method_exchangeImplementations(originalMethod, swizzledMethod);
        }
    });
}

- (void)custom_sendEvent:(UIEvent *)event {
    // 先调用原方法保证系统逻辑正常执行
    [self custom_sendEvent:event];
    
    // 遍历事件中的所有触摸对象
    for (UITouch *touch in event.allTouches) {
        UIView *touchView = touch.view;
        // 判断触摸对象是否为虚拟键盘按键(依赖私有类UIKBKeyView,需注意审核风险)
        if ([NSStringFromClass([touchView class]) isEqualToString:@"UIKBKeyView"]) {
            NSTimeInterval timestamp = touch.timestamp;
            switch (touch.phase) {
                case UITouchPhaseBegan:
                    // 记录按键按下时间戳
                    NSLog(@"Key Down Timestamp: %f", timestamp);
                    // 可通过私有属性获取对应按键字符,例:[touchView valueForKey:@"_key"]
                    break;
                case UITouchPhaseEnded:
                case UITouchPhaseCancelled:
                    // 记录按键抬起时间戳
                    NSLog(@"Key Up Timestamp: %f", timestamp);
                    break;
                default:
                    break;
            }
        }
    }
}

@end

注意:使用私有类和属性存在App Store审核风险,若需规避,可尝试通过触摸位置结合当前输入框上下文推断按键,但准确性会有所降低。

方案二:自定义键盘Extension

通过创建iOS键盘扩展(Keyboard Extension),可完全基于公开API捕获按键的按下/抬起事件,无审核风险:

  1. 创建Keyboard Extension Target,在KeyboardViewController中实现按键逻辑:
@interface KeyboardViewController () <UIInputViewAudioFeedback>
@end

@implementation KeyboardViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // 自定义键盘布局,为每个按键绑定按下/抬起事件
}

// 按键按下触发
- (void)keyButtonDown:(UIButton *)sender {
    NSTimeInterval keyDownTimestamp = CACurrentMediaTime();
    NSLog(@"Key Down Timestamp: %f", keyDownTimestamp);
    // 可选:播放系统按键音效
    [[UIDevice currentDevice] playInputClick];
}

// 按键抬起触发
- (void)keyButtonUp:(UIButton *)sender {
    NSTimeInterval keyUpTimestamp = CACurrentMediaTime();
    NSLog(@"Key Up Timestamp: %f", keyUpTimestamp);
    // 将按键内容发送至宿主App的输入框
    [self.textDocumentProxy insertText:sender.titleLabel.text];
}

@end

缺点:需要用户在系统设置中手动启用该自定义键盘,使用门槛较高;优点是完全合规,时间戳精度高。

方案三:折中估算方案(不推荐高精度场景)

若无法使用上述方案,可通过UITextFieldDelegate结合NotificationCenter监听文本变化,配合定时器近似估算按键时间,但无法精准获取单个按键的按下/抬起时刻,仅适合对精度要求较低的场景。

内容的提问来源于stack exchange,提问作者Baal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 17:36:23