はじめに
普段は Laravel や Nuxt を使って Web アプリケーションを開発しているのですが、年に数回 iOS アプリに改修が入ることがあります。
Swift を触っていない期間が空いていて、これどうするんだっけ?という事が多いので、メモ代わりに投稿します。
概要
リーダー画面(ReaderPage)でQRコードを読み込んだら、同意画面(AgreementPage)をモーダルのフルスクリーンモードで表示し、同意ボタンを押下すると、モーダルを閉じて「同意済み」と表示する機能を実装します。
同意ボタンを押下すると dismiss()
でモーダルを閉じるため、その前に同意済みフラグを立てる方法を2つ紹介します。
また、本アプリケーションでは画面遷移に performSegue()
を使用しています。
環境
- Apple M1 Max
- macOS Monterey (v12.6)
- Xcode 13.2.1
- Swift 5
- iPadOS 16.3.1
コールバック関数を渡して実行する
一つ目はコールバック関数を渡して実行する方法を紹介します。
まずは AgreementPageViewController
にコールバックを格納する変数を定義して、設定されていれば実行されるようにします。
class AgreementPageViewController: UIViewController {
public var agreeCallback: (() -> Void)?
private func agree() {
self.agreeCallback?()
self.dismiss(animated: true)
}
}
画面遷移する前に prepare
という関数が発火されるのですが、この関数の引数の segue.destination
に AgreementPageViewController
が格納されています。
この AgreementPageViewController
にコールバック関数を設定することで実現できます。
class ReaderPageViewController: UIViewController {
private var isAgreed: Bool = false
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
super.prepare(for: segue, sender: sender)
if segue.identifier == "AgreementPage" {
let vc = segue.destination as! AgreementPageViewController
vc.agreeCallback = {
self.isAgreed = true
})
}
}
}
Delegate を設定して実行する
二つ目はデリゲートを設定して実行する方法を紹介します。
まずは、コールバック関数と同じように AgreementPageViewController
にデリゲートを格納する変数を定義して、設定されていれば実行されるようにします。
さらに protocol
で専用のデリゲートを定義します。
class AgreementPageViewController: UIViewController {
private var delegate: AgreementPageViewControllerDelegate?
private func agree() {
self.delegate?.agree()
self.dismiss(animated: true)
}
public func setAgreementPageViewControllerDelegate(_ delegate: AgreementPageViewControllerDelegate) {
self.delegate = delegate
}
}
protocol AgreementPageViewControllerDelegate: NSObjectProtocol {
func agree()
}
ReaderPageViewController
に上記で定義したデリゲートを継承して、関数に処理を書きます。
そして prepare
関数内で AgreementPageViewController
の delegate
に、 ReaderPageViewController
を設定することで、同意ボタン押下時に任意の処理を実行することができるようになります。
class ReaderPageViewController: UIViewController {
private var isAgreed: Bool = false
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
super.prepare(for: segue, sender: sender)
if segue.identifier == "AgreementPage" {
let vc = segue.destination as! AgreementPageViewController
vc.setAgreementPageViewControllerDelegate(self)
}
}
}
extension ReaderPageViewController: AgreementPageViewControllerDelegate {
func agree() {
self.isAgreed = true
}
}
おわりに
画面遷移や画面を跨いだデータのやり取りで Delegate ってどう使うんだっけ?となったので、記事にまとめました!
まだデリゲートパターンを理解して切れていないところがあるので、間違った使い方をしていた場合は、ご指摘頂けると助かります!