環境
- Xcode 12.4
- Swift 5.3.2
内容
iPhoneのPhotosアプリ内でアルバムを新規作成する際、
以下のようなアラートが表示されます。
Photos |
---|
初めは UIAlertAction
の Save
アクションが選択できないようになっています。
UIAlertController
内の UITextField
に文字を入力することで、
先のアクションが選択できるようになります。
今回はこちらを2つの方法で実現してみます。
下準備
適当にラベルとボタンを配置します。
ラベルはアラートで入力した文字列を表示するために用意しています。
SampleViewController |
---|
実装
①愚直に実装
SampleViewController.swift
final class SampleViewController: UIViewController {
private let label = UILabel()
private let button = UIButton(type: .system)
private var saveAction: UIAlertAction!
/*
label, button等のUI処理
*/
// ボタン押下時のアクション
@objc private func showTextFieldAlert() {
let alert = UIAlertController(title: "New Label",
message: "Enter a name for the label.",
preferredStyle: .alert)
// textField
alert.addTextField(configurationHandler: { [weak self] textField in
textField.placeholder = "Label text"
textField.delegate = self
})
// cancel action
let cancelAction = UIAlertAction(title: "Cancel",
style: .cancel)
alert.addAction(cancelAction)
// save action
saveAction = UIAlertAction(title: "Save",
style: .default,
handler: { [weak alert] _ in
let inputText = alert?.textFields?.first?.text
self.label.text = inputText
})
saveAction.isEnabled = false
alert.addAction(saveAction)
present(alert, animated: true)
}
}
extension SampleViewController: UITextFieldDelegate {
func textFieldDidChangeSelection(_ textField: UITextField) {
saveAction.isEnabled = !(textField.text?.trimmingCharacters(in: .whitespaces) ?? "").isEmpty
}
}
改善したい点
- 制御したいアクションをクラスのメンバ変数として用意している
- ViewControllerに別のUITextFieldを用意する場合、Delegateのメソッド内でUITextFieldの判別をする必要がある
こちらを踏まえた上で別の方法に進みます。
②UIActionを活用
iOS14から追加された以下のプロパティとメソッドを利用します。
- Apple Developer Document - sender
- Apple Developer Document - addAction(_:for:)
SampleViewController.swift
final class SampleViewController: UIViewController {
private let label = UILabel()
private let button = UIButton(type: .system)
/*
label, button等のUI処理
*/
// ボタン押下時のアクション
@objc private func showTextFieldAlert() {
let alert = UIAlertController(title: "New Label",
message: "Enter a name for the label.",
preferredStyle: .alert)
// cancel action
let cancelAction = UIAlertAction(title: "Cancel",
style: .cancel)
alert.addAction(cancelAction)
// save action
let saveAction = UIAlertAction(title: "Save",
style: .default) { [weak alert] _ in
self.label.text = alert?.textFields?.first?.text
}
saveAction.isEnabled = false
alert.addAction(saveAction)
// textField
let action = UIAction(handler: { action in
guard let textField = action.sender as? UITextField else { return }
saveAction.isEnabled = !(textField.text?.trimmingCharacters(in: .whitespaces) ?? "").isEmpty
})
alert.addTextField() { textField in
textField.placeholder = "Label text"
textField.addAction(action, for: .editingChanged)
}
present(alert, animated: true)
}
}
これで①の改善したい点を解決できたかと思います。