【问题标题】:Disable Swift UIAlertController button until input validated禁用 Swift UIAlertController 按钮,直到输入验证
【发布时间】:2018-09-28 05:50:27
【问题描述】:

我有一个表格视图,带有一个导航按钮,按下该按钮时会通过警报控制器提示用户输入一个类别,然后将其插入表格中。我不希望用户提交空字符串或已经存在的类别。这是我到目前为止的代码:

   @objc func promptForCategory() {
    let ac = UIAlertController(title: "Enter a category", message: nil, preferredStyle: .alert)
    ac.addTextField()

    let submitCategory = UIAlertAction(title: "Enter", style: .default) { [unowned self, ac] (action: UIAlertAction) in
        let answer = ac.textFields![0]
        self.enter(answer: answer.text!)
    }

    ac.addAction(submitCategory)
    ac.addAction(UIAlertAction(title: "Cancel", style: .cancel))
    present(ac, animated: true)
}

func enter(answer: String) {
    if isBlank(answer: answer) {
        if doesContain(answer: answer) {
            categories.append(answer)
            let indexPath = IndexPath(row: 0, section: 0)
            tableView.insertRows(at: [indexPath], with: .automatic)

        }
    }
}

func isBlank(answer: String) -> Bool {
    return answer != ""
}

func doesContain(answer: String) -> Bool {
    let uppercased = categories.map {$0.uppercased()}
    return !uppercased.contains(answer)
}

有没有办法在通过验证测试之前禁用“Enter”按钮?

【问题讨论】:

    标签: swift uialertcontroller


    【解决方案1】:

    显然你可以放

    你想要的任何代码都在?

    func okHandler(alert: UIAlertAction!)
    {
        // Whatever code you want
    }
    
    yourAlert.addAction(UIAlertAction(title: "OK", style: .default, handler: okHandler))
    

    这将取决于您需要什么。

    现在,

    我在这些帖子中找不到我想要的答案,所以我必须弄清楚。

    如果有人需要在不按上面的按钮的情况下关闭 UIAlert,这就是我为我的应用程序所做的。 我希望它在按下按钮之前消失,这样它就不会干扰其他事情。

    DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(3), execute:
    {
         yourAlert.dismiss(animated: true, completion: nil)
    })
    

    【讨论】:

      【解决方案2】:

      使用此警报使用验证规则 TextValidationRule.nonEmpty

      import UIKit
      
      /// A validation rule for text input.
      public enum TextValidationRule {
          /// Any input is valid, including an empty string.
          case noRestriction
          /// The input must not be empty.
          case nonEmpty
          /// The enitre input must match a regular expression. A matching substring is not enough.
          case regularExpression(NSRegularExpression)
          /// The input is valid if the predicate function returns `true`.
          case predicate((String) -> Bool)
      
      
          public func isValid(_ input: String) -> Bool {
              switch self {
              case .noRestriction:
                  return true
              case .nonEmpty:
                  return !input.isEmpty
              case .regularExpression(let regex):
                  let fullNSRange = NSRange(input.startIndex..., in: input)
                  return regex.rangeOfFirstMatch(in: input, options: .anchored, range: fullNSRange) == fullNSRange
              case .predicate(let p):
                  return p(input)
              }
          }
      
      }
      
      
      extension UIAlertController {
      
          public enum TextInputResult {
              /// The user tapped Cancel.
              case cancel
              /// The user tapped the OK button. The payload is the text they entered in the text field.
              case ok(String)
          }
      
      
          /// Creates a fully configured alert controller with one text field for text input, a Cancel and
          /// and an OK button.
          ///
          /// - Parameters:
          ///   - title: The title of the alert view.
          ///   - message: The message of the alert view.
          ///   - cancelButtonTitle: The title of the Cancel button.
          ///   - okButtonTitle: The title of the OK button.
          ///   - validationRule: The OK button will be disabled as long as the entered text doesn't pass
          ///     the validation. The default value is `.noRestriction` (any input is valid, including
          ///     an empty string).
          ///   - textFieldConfiguration: Use this to configure the text field (e.g. set placeholder text).
          ///   - onCompletion: Called when the user closes the alert view. The argument tells you whether
          ///     the user tapped the Close or the OK button (in which case this delivers the entered text).
          public convenience init(title: String, message: String? = nil,
                                  cancelButtonTitle: String, okButtonTitle: String,
                                  validate validationRule: TextValidationRule = .noRestriction,
                                  textFieldConfiguration: ((UITextField) -> Void)? = nil,
                                  onCompletion: @escaping (TextInputResult) -> Void) {
              self.init(title: title, message: message, preferredStyle: .alert)
      
              /// Observes a UITextField for various events and reports them via callbacks.
              /// Sets itself as the text field's delegate and target-action target.
              class TextFieldObserver: NSObject, UITextFieldDelegate {
      
                  let textFieldValueChanged: (UITextField) -> Void
                  let textFieldShouldReturn: (UITextField) -> Bool
      
                  init(textField: UITextField, valueChange: @escaping (UITextField) -> Void, shouldReturn: @escaping (UITextField) -> Bool) {
      
                      textFieldValueChanged = valueChange
                      textFieldShouldReturn = shouldReturn
                      super.init()
                      textField.delegate = self
                      textField.addTarget(self, action: #selector(TextFieldObserver.textFieldValueChanged(sender:)), for: .editingChanged)
                  }
      
                  @objc func textFieldValueChanged(sender: UITextField) {
                      textFieldValueChanged(sender)
                  }
                  func textFieldShouldReturn(_ textField: UITextField) -> Bool {
                      return textFieldShouldReturn(textField)
                  }
              }
      
      
              var textFieldObserver: TextFieldObserver?
      
               // Every `UIAlertAction` handler must eventually call this
              func finish(result: TextInputResult) {
                  // Capture the observer to keep it alive while the alert is on screen
                  textFieldObserver = nil
                  onCompletion(result)
              }
      
              let cancelAction = UIAlertAction(title: cancelButtonTitle, style: .cancel, handler: { _ in
                  finish(result: .cancel)
              })
              let okAction = UIAlertAction(title: okButtonTitle, style: .default, handler: { [unowned self] _ in
                  finish(result: .ok(self.textFields?.first?.text ?? ""))
              })
      
              addAction(cancelAction)
              addAction(okAction)
      
              preferredAction = okAction
      
              addTextField { textField in
                  textFieldConfiguration?(textField)
                  textFieldObserver = TextFieldObserver(textField: textField, valueChange: { textField in
                      okAction.isEnabled = validationRule.isValid(textField.text ?? "")
                  }, shouldReturn: { textField -> Bool in
                     return validationRule.isValid(textField.text ?? "")
                  })
              }
      
              // Start with a disabled OK button if necessary
              okAction.isEnabled = validationRule.isValid(textFields?.first?.text ?? "")
          }
      
      }
      

      //视图控制器中的示例用法

       let alert = UIAlertController(title: "Alert", cancelButtonTitle: "Cancel", okButtonTitle: "Ok", validate: TextValidationRule.nonEmpty) { _ in
      
              }
              present(alert, animated: true, completion: nil)
      

      【讨论】:

      • 谢谢。但是,在 ViewController 中使用时,出现以下错误:“使用未解析的标识符 'TextValidationRule'” - 我该如何解决?
      • 欢迎,您是否包含了公开的 TextValidationRule 枚举?
      • @M.Lovegrove 你有解决办法吗?如果得到请接受这个答案,它将帮助其他人识别最佳选择。
      【解决方案3】:

      您可以通过使用禁用/启用UIAlertAction

      alertAction.isEnabled = false (or) true
      

      在您的代码中

      submitCategory.isEnabled = false
      

      ac.actions.first?.isEnabled = false
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-02-09
        • 2011-02-02
        • 1970-01-01
        • 2013-05-21
        相关资源
        最近更新 更多