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

如何让UIHostingController中的SwiftUI视图自适应内容大小

如何让UIHostingController中的SwiftUI视图自适应内容大小?

问题说明

手动给UIHostingController的view设置固定frame时,SwiftUI视图可以正常显示,但无法像常规SwiftUI视图一样自动适配内容的固有尺寸。本次需求是要将该SwiftUI视图作为Google Maps标记的iconView属性使用(GMSMarker仅接受UIView类型的视图)。

原始代码示例

import UIKit
import SwiftUI

struct HelloWorld: View {
    var body: some View {
        VStack {
            Image(systemName: "globe")
                .imageScale(.large)
                .foregroundColor(.accentColor)
            Text("Hello, world!")
        }
    }
}

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Do any additional setup after loading the view.
        let viewController = UIHostingController(rootView: HelloWorld())

        // 这里需要手动设置frame,无法自动适配内容
        viewController.view.frame = CGRect(x: 0, y: 0, width: 200, height: 200)
        self.view.addSubview(viewController.view)
    }

}

适配方案(iOS 16及以上)

直接添加UIHostingController的view作为子视图无法自动适配,正确的做法是将其添加为子视图控制器,并配置尺寸适配选项:

  1. 初始化UIHostingController后,设置其sizingOptions为[.intrinsicContentSize],让控制器自动根据SwiftUI内容的固有尺寸调整view大小
  2. 将该UIHostingController添加为当前视图控制器的子控制器,而不是直接添加其view

修改后的代码示例

import UIKit
import SwiftUI

struct HelloWorld: View {
    var body: some View {
        VStack {
            Image(systemName: "globe")
                .imageScale(.large)
                .foregroundColor(.accentColor)
            Text("Hello, world!")
        }
    }
}

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        
        let hostingVC = UIHostingController(rootView: HelloWorld())
        // 设置自动适配内容尺寸
        hostingVC.sizingOptions = [.intrinsicContentSize]
        // 添加为子控制器
        addChild(hostingVC)
        self.view.addSubview(hostingVC.view)
        hostingVC.didMove(toParent: self)
        
        // 如果需要调整位置,可以设置约束,比如居中
        hostingVC.view.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            hostingVC.view.centerXAnchor.constraint(equalTo: view.centerXAnchor),
            hostingVC.view.centerYAnchor.constraint(equalTo: view.centerYAnchor)
        ])
    }
}

Google Maps标记使用示例

如果要将该视图作为GMSMarker的iconView,可以直接将hostingVC.view赋值给属性,此时view已经自动适配了内容尺寸:

let marker = GMSMarker()
marker.position = CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
marker.title = "Title"
marker.iconView = hostingVC.view
marker.map = mapView

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 15:07:55