You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

混合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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 18:42:41