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