停止 UIKeyCommand 重复动作
Stop UIKeyCommand repeated actions
如果注册了一个键命令,如果用户按住键的时间过长,它的操作可能会被调用多次。这会产生非常奇怪的效果,例如 ⌘N 可以多次重复打开新视图。有什么简单的方法可以在不求助于布尔 "already triggered" 标志的情况下停止这种行为?
以下是我如何注册两个不同的键盘命令:
#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
一般来说,您不需要处理这个问题,因为新视图通常会成为 firstReponder 并且会停止重复。对于 playSound 案例,用户会意识到发生了什么,然后将手指从按键上移开。
也就是说,在某些实际情况下,特定的键绝不能重复。如果苹果为此提供 public API 就好了。据我所知,他们没有。
考虑到您代码中的“//在 AppStore 中不允许”注释,您似乎可以使用私有 API。在这种情况下,您可以使用以下命令禁用 keyCommand 的重复:
UIKeyCommand *keyCommand = [UIKeyCommand ...];
[keyCommand setValue:@(NO) forKey:@"_repeatable"];
这适用于 iOS 12,与接受的答案相比 'private' 少了一点:
let command = UIKeyCommand(...)
let repeatableConstant = "repeatable"
if command.responds(to: Selector(repeatableConstant)) {
command.setValue(false, forKey: repeatableConstant)
}
我修改了@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。
如果注册了一个键命令,如果用户按住键的时间过长,它的操作可能会被调用多次。这会产生非常奇怪的效果,例如 ⌘N 可以多次重复打开新视图。有什么简单的方法可以在不求助于布尔 "already triggered" 标志的情况下停止这种行为?
以下是我如何注册两个不同的键盘命令:
#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
一般来说,您不需要处理这个问题,因为新视图通常会成为 firstReponder 并且会停止重复。对于 playSound 案例,用户会意识到发生了什么,然后将手指从按键上移开。
也就是说,在某些实际情况下,特定的键绝不能重复。如果苹果为此提供 public API 就好了。据我所知,他们没有。
考虑到您代码中的“//在 AppStore 中不允许”注释,您似乎可以使用私有 API。在这种情况下,您可以使用以下命令禁用 keyCommand 的重复:
UIKeyCommand *keyCommand = [UIKeyCommand ...];
[keyCommand setValue:@(NO) forKey:@"_repeatable"];
这适用于 iOS 12,与接受的答案相比 'private' 少了一点:
let command = UIKeyCommand(...)
let repeatableConstant = "repeatable"
if command.responds(to: Selector(repeatableConstant)) {
command.setValue(false, forKey: repeatableConstant)
}
我修改了@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。