【问题标题】:Stop UIKeyCommand repeated actions停止 UIKeyCommand 重复动作
【发布时间】:2017-06-03 12:59:22
【问题描述】:

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

【问题讨论】:

    标签: ios iphone ipad uikeycommand


    【解决方案1】:

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

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

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

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

    【讨论】:

    • 这不是公共 API 的一部分,这太疯狂了。感谢您的帮助!
    【解决方案2】:

    这在 iOS 12 中有效,与公认的答案相比,它的“私密性”要少一些:

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

    【讨论】:

      【解决方案3】:

      我稍微修改了@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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-03-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-04-24
        • 1970-01-01
        • 2012-03-23
        相关资源
        最近更新 更多