停止UIKeyCommand重复操作

时间:2017-01-18 23:45:17

标签: ios iphone ipad uikeycommand

如果注册了一个键命令,如果用户按住该键的时间过长,则可能会多次调用该操作。这可能会产生非常奇怪的效果,例如⌘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

3 个答案:

答案 0 :(得分:4)

通常,您不需要处理此问题,因为新视图通常会成为第一个响应者,并且会停止重复。对于playSound案例,用户会意识到正在发生的事情并将手指从钥匙上移开。

也就是说,有些情况下特定键不应重复。如果Apple提供了一个公共API,那将是很好的。据我所知,他们没有。

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

UIKeyCommand *keyCommand =  [UIKeyCommand ...];
[keyCommand setValue:@(NO) forKey:@"_repeatable"];

答案 1 :(得分:1)

我对@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 一起使用。

答案 2 :(得分:0)

这在iOS 12中有效,与接受的答案相比,“私有”要少一些:

let command = UIKeyCommand(...)   
let repeatableConstant = "repeatable"
if command.responds(to: Selector(repeatableConstant)) {
    command.setValue(false, forKey: repeatableConstant)
}