7

如果注册了一个键盘命令,如果用户按住该键的时间过长,它的操作可能会被调用很多次。这会产生非常奇怪的效果,例如 ⌘N 可以多次重复打开新视图。有没有简单的方法来阻止这种行为,而无需诉诸诸如布尔“已触发”标志之类的东西?

以下是我注册两个不同键命令的方法:

#pragma mark - KeyCommands

- (BOOL)canBecomeFirstResponder {
    return YES;
}

- (NSArray<UIKeyCommand *>*)keyCommands {
    return @[
             [UIKeyCommand keyCommandWithInput:@"O" modifierFlags:UIKeyModifierCommand action:@selector(keyboardShowOtherView:) discoverabilityTitle:@"Show Other View"],
             [UIKeyCommand keyCommandWithInput:@"S" modifierFlags:UIKeyModifierCommand action:@selector(keyboardPlaySound:) discoverabilityTitle:@"Play Sound"],
             ];
}

- (void)keyboardShowOtherView:(UIKeyCommand *)sender {
    NSLog(@"keyboardShowOtherView");
    [self performSegueWithIdentifier:@"showOtherView" sender:nil];
}

- (void)keyboardPlaySound:(UIKeyCommand *)sender {
    NSLog(@"keyboardPlaySound");
    [self playSound:sender];
}

#pragma mark - Actions

- (IBAction)playSound:(id)sender {
    AudioServicesPlaySystemSound(1006); // Not allowed in the AppStore
}

可以在此处下载示例项目:TestKeyCommands.zip

4

3 回答 3

7

一般来说,您不需要处理这个问题,因为新视图通常会成为 firstReponder 并且会停止重复。对于 playSound 案例,用户会意识到正在发生的事情并将手指从键上移开。

也就是说,在某些实际情况下,特定键永远不应重复。如果 Apple 为此提供了一个公共 API,那就太好了。据我所知,他们没有。

鉴于代码中的“//AppStore 中不允许”注释,您似乎可以使用私有 API。在这种情况下,您可以使用以下命令禁用 keyCommand 的重复:

UIKeyCommand *keyCommand =  [UIKeyCommand ...];
[keyCommand setValue:@(NO) forKey:@"_repeatable"];
于 2017-10-30T01:45:29.347 回答
6

我修改了@Ely的答案:

extension UIKeyCommand {
    var nonRepeating: UIKeyCommand {
        let repeatableConstant = "repeatable"
        if self.responds(to: Selector(repeatableConstant)) {
            self.setValue(false, forKey: repeatableConstant)
        }
        return self
    }
}

现在您可以编写更少的代码。例如,如果只是var keyCommands: [UIKeyCommand]?通过返回一个静态列表来覆盖它,它可以像这样使用:

override var keyCommands: [UIKeyCommand]? {
    return [
        UIKeyCommand(...),
        UIKeyCommand(...),
        UIKeyCommand(...),

        UIKeyCommand(...).nonRepeating,
        UIKeyCommand(...).nonRepeating,
        UIKeyCommand(...).nonRepeating,
    ]
}

这使得前三个命令重复(如增加字体大小)和后三个不重复(如发送电子邮件)。

适用于Swift 4、iOS 11

于 2019-08-11T16:00:39.523 回答
3

这适用于 iOS 12,与接受的答案相比,它的“私密性”要少一些:

let command = UIKeyCommand(...)   
let repeatableConstant = "repeatable"
if command.responds(to: Selector(repeatableConstant)) {
    command.setValue(false, forKey: repeatableConstant)
}
于 2019-04-18T18:57:00.723 回答