Created
September 7, 2018 14:11
-
-
Save jasorod/700fd675d1898be0c7a9bba9112ccc83 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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