混合UIKit与SwiftUI项目中导航栏按钮延迟显示问题求助
问题
App主框架基于UIKit,部分页面采用SwiftUI编写并通过UIHostingController嵌入UIKit中展示。点击UIKit页面的按钮跳转至SwiftUI页面时,右上角的两个工具栏按钮会短暂延迟后才显示,存在闪烁问题。
相关代码如下:
窗口初始化代码
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 }
SwiftUI视图代码
struct ContentView: View { var body: some View { Text("hello world") } }
UIKit视图控制器代码
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) } }
解决方案
方法一:将Toolbar内嵌到SwiftUI视图内部
把toolbar的定义直接放到ContentView的body中,让视图在初始化时就包含完整的toolbar结构,避免push后动态渲染导致的延迟:
struct ContentView: View { var body: some View { Text("hello world") .toolbar { ToolbarItem(placement: .automatic) { Button { //isShowSettingView = true } label: { Image(systemName: "ellipsis.circle") } } ToolbarItem(placement: .automatic) { Button { //addItem() } label: { Image(systemName: "square.and.pencil") } } } } }
修改跳转代码,直接使用原始的ContentView:
@objc func runBtnAction() { let contentView = ContentView() let vc2 = UIHostingController(rootView: contentView) vc2.title = "Hello" navigationController?.pushViewController(vc2, animated: true) }
方法二:提前让SwiftUI视图完成布局计算
如果需要动态配置toolbar(比如根据不同场景显示不同按钮),可以在push前提前触发视图的布局计算,避免push后的渲染延迟:
@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 hostingController = UIHostingController(rootView: contentView) hostingController.title = "Hello" // 提前触发布局计算,完成toolbar的渲染准备 hostingController.view.layoutIfNeeded() navigationController?.pushViewController(hostingController, animated: true) }
原理说明
出现延迟闪烁的核心原因是:跳转前才动态给ContentView附加toolbar,SwiftUI需要在push完成后才开始构建toolbar的视图树并渲染到导航栏,导致按钮显示滞后。通过提前将toolbar整合到视图定义,或者提前触发布局计算,让SwiftUI在push前就完成toolbar的渲染准备,就能消除延迟闪烁问题。
内容的提问来源于stack exchange,提问作者mars
相关产品推荐
相关产品推荐

