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

SwiftUI视图嵌入UIHostingController后布局偏移问题的解决方法

问题:SwiftUI视图嵌入UIHostingController后布局挤到左上角

在基于UIKit的应用中,我开发了一个用于展示无数据状态的SwiftUI视图,通过UIHostingController嵌入展示时,视图内容被挤到屏幕左上角。该视图在纯SwiftUI项目中显示正常,但嵌入后布局异常。

SwiftUI视图代码

struct ContentView: View {
    var body: some View {
        ZStack {
            Color("darkerBlue")
                .ignoresSafeArea()

            VStack(spacing: 20) {
                Image("barbell")
                    .resizable()
                    .aspectRatio(contentMode: .fit)
                    .frame(width: 200, height: 200) // Adjust the image size

                Text("You don't have any lifts saved.")
                    .font(.title)
                    .foregroundColor(.white)
                    .padding()

                Button(action: {
                    // Handle button action
                }) {
                    Text("Do it")
                        .font(.headline)
                        .foregroundColor(.white)
                        .padding(EdgeInsets(top: 8, leading: 50, bottom: 8, trailing: 50))
                        .background(Color("lightBlue"))
                        .cornerRadius(8)
                }
            }
        }
    }
}

嵌入UIHostingController的代码

case .noLiftEvents:
    let emptyLogView = EmptyLogView(coordinator: self)
    let hostingController = UIHostingController(rootView: emptyLogView)
    add(hostingController)
    return hostingController

子控制器添加扩展方法

func add(_ child: UIViewController) {
    addChild(child)
    view.addSubview(child.view)
    child.didMove(toParent: self)
}

问题原因

核心问题是未给UIHostingController的view添加自动布局约束。在UIKit中,添加子控制器视图时,如果不设置约束,子视图不会自动填充父容器,只会以默认的原点(0,0)和固有尺寸(intrinsicContentSize)显示,导致SwiftUI内容被压缩在左上角。

修复方法

修改add(_ child: UIViewController)扩展方法,给子视图添加约束使其完全填充父视图:

func add(_ child: UIViewController) {
    addChild(child)
    // 禁用自动转换约束,避免冲突
    child.view.translatesAutoresizingMaskIntoConstraints = false
    view.addSubview(child.view)
    // 添加四边约束,让子视图完全填充父视图
    NSLayoutConstraint.activate([
        child.view.topAnchor.constraint(equalTo: view.topAnchor),
        child.view.leadingAnchor.constraint(equalTo: view.leadingAnchor),
        child.view.trailingAnchor.constraint(equalTo: view.trailingAnchor),
        child.view.bottomAnchor.constraint(equalTo: view.bottomAnchor)
    ])
    child.didMove(toParent: self)
}

说明

  • translatesAutoresizingMaskIntoConstraints = false:必须设置,否则系统会自动生成基于frame的约束,和我们手动添加的约束产生冲突。
  • 四个方向的约束确保UIHostingController的view完全覆盖父视图,SwiftUI内容就能按照预期居中显示了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 22:02:10