Swift UI:UIHostingController.view 不适合 iOS 13 的内容视图大小

问题描述

iOS 13

iOS 14

我想根据通信结果更新Swift UI View。 但是 UIHostingController.view 不适合 iOS 13 的 rootView 大小。 当我尝试使用下面的示例代码时,也会发生同样的事情。 我想将调整大小的 SwiftUI 视图添加到 UIStackView,但 SwiftUI 视图与上一个和下一个视图重叠,因为这个问题。 我怎样才能避免这个问题?

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        
        let object = SampleObject()
        let sampleView = SampleView(object: object)
        let hosting = UIHostingController(rootView: sampleView)
        hosting.view.backgroundColor = UIColor.green
        addChild(hosting)
        view.addSubview(hosting.view)
        hosting.view.translatesAutoresizingMaskIntoConstraints = false
        hosting.view.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
        hosting.view.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
        hosting.view.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
        hosting.didMove(toParent: self)
        
        dispatchQueue.main.asyncAfter(deadline: .Now() + 1.0) {
            object.test()
        }
    }
}


struct SampleView: View {
    @Observedobject var object: SampleObject
    
    var body: some View {
        vstack {
            Text("test1").background(Color.blue)
            Text("test2").background(Color.red)
            if object.state.isVisibleText {
                Text("test2").background(Color.gray)
            }
        }
        .padding(32)
        .background(Color.yellow)
    }
}


final class SampleObject: ObservableObject {
    struct ViewState {
        var isVisibleText: Bool = false
    }
    
    @Published private(set) var state = ViewState()
    
    func test() {
        state.isVisibleText = true
    }
}

如果像下面这样将Subview添加到UIStackView,Swift UI View的高度在iOS13中不会改变。

enter image description here

iOS13(不正确)

enter image description here

iOS14(正确)

enter image description here

解决方法

你还没有设置底部锚点,添加这一行

hosting.view.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true

另一种简单的方法是将框架设置为托管控制器视图并删除约束。

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        
        let object = SampleObject()
        let sampleView = SampleView(object: object)
        let hosting = UIHostingController(rootView: sampleView)
        hosting.view.frame = UIScreen.main.bounds //<---here
        hosting.view.backgroundColor = UIColor.green
        addChild(hosting)
        view.addSubview(hosting.view)
        hosting.didMove(toParent: self)
        
        DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
            object.test()
        }
    }
}