
【Swift】UIAlertControllerのactionSheetにカスタムViewを埋め込む
この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
UIAlertControllerからactionSheetスタイルで表示したアラートにカスタムViewを埋め込みたくなったので、埋め込み方法を調べました。
環境
- Xcode 14.1
- iOS 16.1
UIAlertController.Style.actionSheet
UIAlertController.Styleを.actionSheetに選択することでiOSデバイスでは下から出てくるアクションシートを表現出来ます。
@IBAction private func showActionSheet(_ sender: UIButton) {
let actionSheet = UIAlertController(title: "かわいいは作れる", message: nil,
preferredStyle: .actionSheet)
// iPadのクラッシュ対応
actionSheet.popoverPresentationController?.sourceView = sender.superview
actionSheet.popoverPresentationController?.sourceRect = sender.frame
let yesAction = UIAlertAction(title: "はい", style: .default)
let noAction = UIAlertAction(title: "いいえ", style: .cancel)
actionSheet.addAction(yesAction)
actionSheet.addAction(noAction)
present(actionSheet, animated: true)
}

このアクションシートにカスタムViewを追加してかわいいを作っていこうと思います。
補足
iPadでUIAlertController.Style.actionSheetを使用するには位置情報の設定が必要で、位置情報を設定しない場合にはクラッシュしてしまう為、sourceViewとsourceRectを設定しています。
// iPadのクラッシュ対応 actionSheet.popoverPresentationController?.sourceView = sender.superview actionSheet.popoverPresentationController?.sourceRect = sender.frame
詳細については以前記事を書いたので今回は省かせていただきます。
UIAlertControllerにカスタムViewを追加する
埋め込むカスタムView
SwiftUIのViewでこのようなViewを作成しました。

UIAlertControllerにaddSubViewをする
作成したカスタムViewをUIAlertController.viewにaddSubViewを行います。
UIAlertControllerのtitleにカスタムViewが良い具合に収まるくらいの改行のテキストを渡します。すると、アラートのタイトル欄が縦に長くなるので、addSubViewをした時に中に収まっているように表現することが出来ます。
@IBAction private func showActionSheet(_ sender: UIButton) {
// 縦方向にスペースを追加し、ActionSheetのタイトルの縦幅を広くする
let verticalSpaceText = "\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
let actionSheet = UIAlertController(title: verticalSpaceText,
message: nil,
preferredStyle: .actionSheet)
// iPadのクラッシュ対応
actionSheet.popoverPresentationController?.sourceView = sender.superview
actionSheet.popoverPresentationController?.sourceRect = sender.frame
let hostingController = UIHostingController(rootView: CuteView())
actionSheet.addChild(hostingController)
// actionSheetにカスタムViewを追加
actionSheet.view.addSubview(hostingController.view)
hostingController.didMove(toParent: actionSheet)
guard let actionSheetView = actionSheet.view else { return }
// レイアウトの調整
hostingController.view.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
hostingController.view.topAnchor.constraint(equalTo: actionSheetView.topAnchor,
constant: 40),
hostingController.view.widthAnchor.constraint(equalTo: actionSheetView.widthAnchor),
])
let yesAction = UIAlertAction(title: "はい", style: .default)
let noAction = UIAlertAction(title: "いいえ", style: .cancel)
actionSheet.addAction(yesAction)
actionSheet.addAction(noAction)
present(actionSheet, animated: true)
}
埋め込みたいViewによって、レイアウトの制約も調整してみてください。
出来たもの
無事にかわいいが作れました。

おわりに
SwiftUIのconfirmationDialogではViewをカスタムすることが出来ず困っていたのですが、UIAlertControllerの.actionSheetを使用してやや力技ですがカスタムすることが出来ました。
UIKit様、この度はお力を借していただきありがとうございました。
是非、皆様のかわいいも作ってみてください。











