Open4

[SwiftUI] 子要素から親要素のdismiss を行う

Yusuke AriyoshiYusuke Ariyoshi

画面を閉じる時の実装パターンを整理したい。

  • SwiftUI のView から親のView を閉じる
  • SwiftUI のView から親のUIHostingController を閉じる
Yusuke AriyoshiYusuke Ariyoshi

SwiftUI のView から親のView を閉じる

import SwiftUI

struct ChildView: View {
    @Environment(\.presentationMode) var presentationMode
   
    var body: some View {
        Button(action: { didTapDismissButton() }) {
            //
        }
    }
  
    private func didTapDismissButton() {
        presentationMode.wrappedValue.dismiss()
    }
}
Yusuke AriyoshiYusuke Ariyoshi

SwiftUI のView から親のUIHostingController を閉じる

共通

import SwiftUI

struct ChildView: View {
    var dismissAction: () -> Void = {}
   
    var body: some View {
        Button(action: { didTapDismissButton() }) {
            //
        }
    }
  
    private func didTapDismissButton() {
        dismissAction()
    }
}

[ケースA] (未確認)

import UIKit
import SwiftUI

class HostingViewController: UIHostingController<ChildView> {       
    required init?(coder: NSCoder) {
        super.init(rootView: ChildView()
        childView.dismissAction = dismissAction
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
    }
    
    func dismissAction() {
        dismiss(animated: true, completion: nil)
    }
}

[ケースB] UIViewController からModal でHostingController をpresent した場合 (Storyboard 利用)

import UIKit
import SwiftUI

protocol HostingViewControllerDelegate: AnyObject {
    func dismissHostingView()
}

class HostingViewController: UIHostingController<ChildView> {       
    required init?(coder: NSCoder) {
        super.init(rootView: ChildView()
        childView.dismissAction = dismissAction
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
    }
    
    func dismissAction() {
        delegate?.dismissHostingView()
    }
}
class HostingParentViewController: UITableViewController, HostingViewControllerDelegate {
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == "toHostingViewController" {
            let vc = segue.destination as! HostingViewController
            vc.delegate = self            
        }
    }
  
    func dismissHostingView() {
        dismiss(animated: true, completion: nil)
    }
}