Skip to content

Instantly share code, notes, and snippets.

@jasorod
Created September 7, 2018 14:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jasorod/700fd675d1898be0c7a9bba9112ccc83 to your computer and use it in GitHub Desktop.
Save jasorod/700fd675d1898be0c7a9bba9112ccc83 to your computer and use it in GitHub Desktop.
import UIKit
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.
/// - validationRegex: A regular expression in string format; the OK button will remain disabled
/// until the text does not match this regex.
/// - 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,
validationRegex: String,
textFieldConfiguration: ((UITextField) -> Void)? = nil,
onCompletion: @escaping (TextInputResult) -> Void) {
self.init(title: title, message: message, preferredStyle: .alert)
var textFieldDidChangeObserver: Any?
// Every `UIAlertAction` handler must eventually call this
func finish(result: TextInputResult) {
if let observer = textFieldDidChangeObserver {
NotificationCenter.default.removeObserver(observer)
}
onCompletion(result)
}
func isTextValid(text: String) -> Bool {
return text.range(of: validationRegex, options: .regularExpression, range: nil, locale: nil) != nil
}
let cancelAction = UIAlertAction(title: cancelButtonTitle, style: .cancel, handler: { _ in
finish(result: .cancel)
})
let createAction = UIAlertAction(title: okButtonTitle, style: .default, handler: { [unowned self] _ in
finish(result: .ok(self.textFields?.first?.text ?? ""))
})
addAction(cancelAction)
addAction(createAction)
preferredAction = createAction
addTextField(configurationHandler: { textField in
textFieldConfiguration?(textField)
// Monitor the text field to disable the OK button when text does not match the regular expression
textFieldDidChangeObserver = NotificationCenter.default.addObserver(forName: .UITextFieldTextDidChange, object: textField, queue: .main) { _ in
createAction.isEnabled = isTextValid(text: textField.text ?? "")
}
})
// Start with a disabled OK button if necessary
if !isTextValid(text: self.textFields?.first?.text ?? "") {
createAction.isEnabled = !(textFields?.first?.text?.isEmpty ?? true)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment