如何让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作为子视图无法自动适配,正确的做法是将其添加为子视图控制器,并配置尺寸适配选项:
- 初始化
UIHostingController后,设置其sizingOptions为[.intrinsicContentSize],让控制器自动根据SwiftUI内容的固有尺寸调整view大小 - 将该
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
相关产品推荐
相关产品推荐

