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

如何在UIKit ViewController中嵌入SwiftUI Chart?编译正常但无UI显示

解决Storyboard中嵌入SwiftUI Chart不显示的问题

你的代码存在几个关键问题,导致图表无法显示,以下是问题分析和修正方案:

核心问题点

  • 视图类型匹配错误:你定义的SwiftUI图表视图是ContentViewChart,但创建实例时误用了ContentView(),加载的不是目标视图。
  • 容器视图未加入层级:创建的蓝色主容器uiView没有添加到当前ViewController的视图层级中,整个容器都不在界面上。
  • Host View无布局约束:将SwiftUI视图的宿主View添加到容器后,未设置尺寸约束,导致SwiftUI视图没有显示空间。
  • 方法内定义结构体不规范:在viewDidLoad内定义Item和ContentViewChart虽能编译,但不符合Swift编码规范,易引发潜在问题。

修正后的完整代码

// 将结构体移到ViewController类外部,符合编码规范
struct Item: Identifiable {
    var id = UUID()
    let type: String
    let value: Double
}

struct ContentViewChart: View {
    let items: [Item] = [
        Item(type: "1", value: 100 ),
        Item(type: "2", value: 80 ),
        Item(type: "3", value: 120 ),
        Item(type: "4", value: 20 ),
        Item(type: "5", value: 55 ),
        Item(type: "6", value: 170 ),
        Item(type: "7", value: 20 ),
        Item(type: "8", value: 10 ),
        Item(type: "9", value: 5 ),
        Item(type: "10", value: 1 ),
        Item(type: "11", value: 500 ),
        Item(type: "12", value: 700 )
    ]
    var body: some View {
        // 移除不必要的NavigationView,避免额外导航栏占用空间
        ScrollView {
            Chart(items) { item in
                LineMark(
                    x: .value("Month", item.type),
                    y: .value("Revenue", item.value)
                )
                .foregroundStyle(Color.purple.gradient)
            }
            .frame(height: 200)
            .padding()
        }
    }
}

class YourViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Revenue Chart
        let size = CGSize(width: 400, height: 400)
        let sizeSubView = CGSize(width: 200, height: 200)
        
        let uiView = UIView(frame: CGRect(origin: .zero, size: size))
        uiView.backgroundColor = .systemBlue
        // 将主容器添加到当前VC的视图层级
        view.addSubview(uiView)
        // 通过约束固定主容器位置(居中显示)
        uiView.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            uiView.centerXAnchor.constraint(equalTo: view.centerXAnchor),
            uiView.centerYAnchor.constraint(equalTo: view.centerYAnchor),
            uiView.widthAnchor.constraint(equalToConstant: size.width),
            uiView.heightAnchor.constraint(equalToConstant: size.height)
        ])
        
        let centerPointForSubView = CGRect(origin: CGPoint(x: 100, y: 100), size: sizeSubView)
        let uiViewSubView = UIView(frame: centerPointForSubView)
        uiViewSubView.backgroundColor = .white
        uiView.addSubview(uiViewSubView)
        
        // 创建正确的SwiftUI视图实例
        let swiftUIView = ContentViewChart()
        let host = UIHostingController(rootView: swiftUIView)
        let hostView = host.view!
        
        // 设置Host View填充整个容器子视图
        hostView.translatesAutoresizingMaskIntoConstraints = false
        uiViewSubView.addSubview(hostView)
        NSLayoutConstraint.activate([
            hostView.topAnchor.constraint(equalTo: uiViewSubView.topAnchor),
            hostView.leadingAnchor.constraint(equalTo: uiViewSubView.leadingAnchor),
            hostView.trailingAnchor.constraint(equalTo: uiViewSubView.trailingAnchor),
            hostView.bottomAnchor.constraint(equalTo: uiViewSubView.bottomAnchor)
        ])
        
        // 绑定Hosting Controller的生命周期,避免视图异常
        addChild(host)
        host.didMove(toParent: self)
    }
}

关键修改说明

  1. 修正视图实例:将ContentView()改为ContentViewChart(),确保加载目标图表视图。
  2. 加入主容器到视图层级:通过view.addSubview(uiView)将蓝色容器添加到界面,并添加约束固定位置。
  3. 设置Host View约束:让宿主View完全填充容器子视图,给SwiftUI视图明确的显示尺寸。
  4. 管理子控制器生命周期:调用addChild和didMove(toParent:),确保UIHostingController与当前VC生命周期同步。
  5. 移除冗余组件:去掉不必要的NavigationView,避免占用容器空间影响图表显示。

内容的提问来源于stack exchange,提问作者flaneur_7508

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 12:25:24