[iOS]標準の UIAlertController で複数行入力する UITextView を利用する


UITextField なら簡単

1行だけ入力する UITextField なら簡単にできる。

let alert = UIAlertController(title:"title", message:"message", preferredStyle: .alert)
alert.addTextField(configurationHandler: { textField in
    textField.placeholder = "placeholder"
    textField.clearButtonMode = .whileEditing
    textField.text = defaultText
})

UITextView などの CustomView を入れたい場合

強引に入れる必要がある。
以下の例だと SnapKit を使っています、自力で Autolayout 書く人は変換してください。

// textView を表示するための高さの担保のため、dummy で改行を表示する
let message = "message" + "\n\n\n\n\n\n\n"
let alert = UIAlertController(title: "title", message: message, preferredStyle: .alert)

let textView = UITextView()
textView.text = defaultText
textView.layer.borderColor = UIColor.lightGray.cgColor
textView.layer.borderWidth = 0.5
textView.layer.cornerRadius = 6

// textView を追加して Constraints を追加
alert.view.addSubview(textView)
textView.snp.makeConstraints { make in
    make.top.equalTo(75)
    make.left.equalTo(10)
    make.right.equalTo(-10)
    make.bottom.equalTo(-60)
}

// 画面が開いたあとでないと textView にフォーカスが当たらないため、遅らせて実行する
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
    textView.becomeFirstResponder()
}

let okAction: UIAlertAction = UIAlertAction(
    title: "OK",
    style: UIAlertActionStyle.default,
    handler: { _ in
        print(textView.text)
    }
)
alert.addAction(okAction)

かなりキワドイコードになっていますが、ポイントは以下です。

  1. message に改行を大量に表示する
    • Alert の高さを担保するため
  2. textView を top: 75, left: 10, right: -10, bottom: -60 で表示
    • Alert のタイトルの下、ボタンの上の領域(改行を大量に入れた部分)にいい感じに textView を表示する
    • キワドイ: 今後アラートの形式が変わると崩れる
  3. 遅延処理で textView にフォーカスを当てる
    • 愚直に textView. becomeFirstResponder() を書いてもダメで、画面描画後にフォーカスを当てる必要がある
    • キワドイ: 0.3 秒は複数端末で試してこれくらいという体感値、0.1 だと反応せず0.5だと遅い

結果

いい感じに表示されました

おまけ: sberrevoets/SDCAlertView

sberrevoets/SDCAlertView を contentView というので綺麗に書けるが、これだけのためにライブラリに依存したくないし使わなかった。