5

I have an app which main framework was developed using uikit, and some of its pages were written by SwiftUI and embedded into uikit for display through UIHostingController. Now there is a Swiftui page, and I want to push to this page by UIHostingController.

The window init code is as bellow:

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        window = UIWindow(frame: UIScreen.main.bounds)
        
        let vc = UINavigationController(rootViewController: ViewController())
        
        window?.rootViewController = vc
        window?.makeKeyAndVisible()
        return true
    }

Then is the SwiftUI View:

struct ContentView: View {
    var body: some View {
        Text("hello world")
    }
}

Then is the UIKit vc:

import UIKit
import SwiftUI

class ViewController: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .white
        view.addSubview(runBtn)
        runBtn.frame = CGRect(x: 100, y: 200, width: 200, height: 50)
    }
    
    lazy var runBtn: UIButton  = {
        let btn = UIButton()
        btn.setTitle("Push to SwiftUI View", for: .normal)
        btn.setTitleColor(.blue, for: .normal)
        btn.addTarget(self, action: #selector(runBtnAction), for: .touchUpInside)
        return btn
    }()
    
    @objc func runBtnAction() {
        let contentView = ContentView()
            .toolbar {
                ToolbarItem(placement: .automatic) {
                    Button {
                        //isShowSettingView = true
                    } label: {
                        Image(systemName: "ellipsis.circle")
                    }
                }
                ToolbarItem(placement: .automatic) {
                    Button {
                        //addItem()
                    } label: {
                        Image(systemName: "square.and.pencil")
                    }
                }
            }
        let vc2 = UIHostingController(rootView: contentView)
        vc2.title = "Hello"

        navigationController?.pushViewController(vc2, animated: true)
    }
}

After click the button, it can push the SwiftUI View. However, the two buttons in the upper right corner will only be displayed after a short delay. How can I solve this problem? How can it be displayed directly instead of flashing.

0

1 Answer 1

3

After couple of hours this is what fixed my issue:

let controller = UIHostingController(rootView: builder(route))
navigationController.pushViewController(controller, animated: true)
navigationController.setNavigationBarHidden(true, animated: false)
navigationController.setNavigationBarHidden(false, animated: false)

It disabled button appearance animations in the toolbar but you can add you own animation, for example:

ToolbarItem(placement: .navigationBarLeading) {
  NavigationBarButton(type: barButtonType) {
    alpha = .zero
    dismiss()
  }
  .opacity(alpha)
  .animation(.default, value: alpha)
  .onAppear {
     alpha = 1.0
  }
}
Sign up to request clarification or add additional context in comments.

1 Comment

how does it work?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.