Reputation: 666
Would like to return to my presenting UIKit View Controller after pressing the save button on my SwiftUI View (presented via a HostingViewController).
This is how a navigate to my SwiftUI view from my UIKit VC.
let profileView = suiProfileView().environmentObject(suiProfileViewModel())
let profileVC = UIHostingController(rootView: profileView)
let navVC = UINavigationController(rootViewController: profileVC)
navVC.modalPresentationStyle = .fullScreen
SideMenuManager.default.leftMenuNavigationController?.present(navVC, animated: true , completion: nil)
This is my SwiftUI View that i'd like to dismiss after pressing the Save button
import SwiftUI
import Combine
struct suiProfileView: View {
@SwiftUI.Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
@EnvironmentObject var profileViewModel: suiProfileViewModel
@State var suiTitleText = t("general.save")
var body: some View {
GeometryReader { geo in
VStack {
personalInfoSection
Spacer()
Button("Save", action: profileViewModel.saveProfile)
.frame(width: geo.size.width * 0.8, height: geo.size.height * 0.08, alignment: .center)
}
.onReceive(profileViewModel.viewDismissalModePublisher) { shouldDismiss in
if shouldDismiss {
self.presentationMode.wrappedValue.dismiss()
}
}
.frame(width: geo.size.width, height: geo.size.height, alignment: .center)
.padding()
}
}
}
This is my ProfileViewModel class which publishes the shouldDismissView variable using Combine after running some business logic.
class suiProfileViewModel: suiProfileViewModelProtocol {
//private var model: suiProfileFormProtocol
@Published var profile = suiProfileForm()
var viewDismissalModePublisher = PassthroughSubject<Bool, Never>()
private var shouldDismissView = false {
didSet {
viewDismissalModePublisher.send(shouldDismissView)
}
}
func businessLogicThatDeterminesIfShouldDismissView() {
//....
}
}
For some reason self.presentationMode.wrappedValue.dismiss()
which was called in my SwiftUI view is not dismissing my SwiftUI view and not allowing me to go back to my initial UIKit View Controller who presented it in the first place. Any help would greatly appreciated. Thanks in advance
Upvotes: 5
Views: 2369
Reputation: 52426
A couple problems that I see:
You're trying to dismiss your suiProfileView
, but really, it's wrapped in a UINavigationController
before you present it.
According to a basic test that I just did, even if your suiProfileView
were presented without the navigation controller, presentationMode
still doesn't work on it -- my suspicion is that it's only passed accurately when going SwiftUI->SwiftUI and can't be trusted to be communicated through the UIHostingController
I would suggest passing a closure to suiProfileView
that can run the dismiss
code from your original presenting view controller. Here's a simplified example:
import UIKit
import SwiftUI
class ViewController: UIViewController {
var presentedController : UINavigationController?
func dismissVC() {
presentedController?.dismiss(animated: true)
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
let swiftUIView = ContentView(dismiss: self.dismissVC)
let hostVC = UIHostingController(rootView: swiftUIView)
let navVC = UINavigationController(rootViewController: hostVC)
navVC.modalPresentationStyle = .fullScreen
self.present(navVC, animated: true , completion: nil)
self.presentedController = navVC
}
}
}
struct ContentView : View {
var dismiss : () -> Void
@Environment(\.presentationMode) private var presentationMode: Binding<PresentationMode>
var body: some View {
Button(action: {
dismiss()
//presentationMode.wrappedValue.dismiss() <-- doesn't function
}) {
Text("Close")
}
}
}
Upvotes: 7