嵌入 UIHostingController 时无法将 SwiftUI 视图放置在 SafeArea 之外

Wal*_*ter 15 uikit safearealayoutguide swiftui uihostingcontroller

我有一个简单的 SwiftUI 视图,其中包含 3 个文本元素:

\n
struct ImageDescriptionView: View {\n    var title: String?\n    var imageDescription: String?\n    var copyright: String?\n\n    var body: some View {\n        VStack(alignment: .leading) {\n        \n            if let title = title {\n                Text(title)\n                    .fontWeight(.bold)\n                    .foregroundColor(.white)\n                    .frame(maxWidth: .infinity, alignment: .leading)\n            }\n        \n            if let imageDescription = imageDescription {\n                Text(imageDescription)\n                    .foregroundColor(.white)\n                    .fontWeight(.medium)\n                    .frame(maxWidth: .infinity, alignment: .leading)\n            }\n        \n            if let copyright = copyright {\n                Text(copyright)\n                    .font(.body)\n                    .foregroundColor(.white)\n                    .frame(maxWidth: .infinity, alignment: .leading)\n            }\n        \n        }\n        .background(\n            Color.blue\n        )\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

SwiftUI 视图嵌入在UIHostingController

\n
class ViewController: UIViewController {\n\n    private var hostingController = UIHostingController(rootView: ImageDescriptionView(title: "25. November 2021", imageDescription: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.", copyright: "Bild \xc2\xa9 Unknown"))\n\n    override func viewDidLoad() {\n        super.viewDidLoad()\n        setUpHC()\n    }\n\n    private func setUpHC() {\n        hostingController.view.backgroundColor = .red\n    \n        view.addSubview(hostingController.view)\n        hostingController.view.translatesAutoresizingMaskIntoConstraints = false\n        NSLayoutConstraint.activate([\n            hostingController.view.leadingAnchor.constraint(equalTo: view.leadingAnchor),\n            hostingController.view.trailingAnchor.constraint(equalTo: view.trailingAnchor),\n            hostingController.view.bottomAnchor.constraint(equalTo: view.bottomAnchor)\n        ])\n        addChild(hostingController)\n        hostingController.didMove(toParent: self)\n    }\n\n}\n
Run Code Online (Sandbox Code Playgroud)\n

结果如下:

\n

在此输入图像描述

\n

UIHostingController 总是比视图大。另外,它总是使 SwiftUI 视图尊重安全区域(在我的情况下,我不想要)

\n

我想要的外观:

\n

(请不要评论home指示器的可用性,这里不是这样的)

\n

在此输入图像描述

\n

UIHostingController 有什么问题?我尝试在 中的所有视图上设置 .edgesIgnoreSafeArea(.all) ImageDescriptionView,但没有帮助。

\n

小智 12

在 UIHostingControllers 属性上尝试以下操作

viewController._disableSafeArea = true
Run Code Online (Sandbox Code Playgroud)

这应该够了吧。

  • 由于它是私有 API,有人测试过 AppStore 版本吗? (3认同)
  • 这对我有用,有人上传到应用商店了吗? (2认同)

Pra*_*tti 10

iOS 16.4 更新

iOS 16.4 中现在为之前的私有 API 方法提供了官方 API:

viewController.safeAreaRegions = SafeAreaRegions()
Run Code Online (Sandbox Code Playgroud)

初始化SafeAreaRegions()器返回一个空集合。.safeAreaRegions默认值为.all

向后兼容的答案

如果你想向后兼容并支持 iOS 13+,有一个解决方法:

let controller = UIHostingController(rootView: buttonView)
let window = UIApplication.shared.windows.first(where: \.isKeyWindow)
let inverseSafeAreaInset = window?.safeAreaInsets.bottom ?? 0
controller.additionalSafeAreaInsets = UIEdgeInsets(top: 0, left: 0, bottom: -inverseSafeAreaInset, right: 0)
Run Code Online (Sandbox Code Playgroud)

请注意,您可以通过多种方式获取相对于父视图/VC 的反向偏移量。例如,view.safeAreaInsets一旦视图被展示出来就可以工作,但是该window方法适用于所有情况。


Wal*_*ter 0

正如亚历克斯在对我的问题的评论中提到的那样,苹果似乎解决了这个问题。

Xcode 14.3、iOS 16 模拟器

在此输入图像描述