在Swift中将SwiftUI视图添加到UIKit UIView中

44

我尝试使用addSubview将SwiftUI视图添加到UIView上。self.view.addSubview(contentView)

错误:无法将类型为'ContentView'的值转换为预期的参数类型'UIView'

请帮助我实现这个界面。

import UIKit
import SwiftUI

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        view.backgroundColor = UIColor.lightGray
        
        let contentView = ContentView()
        view.addSubview(contentView) // Error: Cannot convert value of type 'ContentView' to expected argument type 'UIView'
    }


}


struct ContentView: View {
    var body: some  View {
        Text("Hello world")
    }
    
}

View protocol != a UIView - Ashley Mills
观看第231节“集成SwiftUI”的非常第一部分。您需要使用UIHostingController。https://developer.apple.com/videos/play/wwdc2019/231/ - user7014451
抱歉发了第二条评论。由于UIHostingController是一个UIViewController ,并且您希望使用addSubview,因此您还需要学习如何使用子视图控制器(在UIKit中完成),其中一部分涉及将视图添加为父视图的子视图。托管控制器(适用于UIKit、AppKit和WatchKit)是完整的控制器,并且很容易用于全屏* SwiftUI 视图。希望这可以帮助到您。 - user7014451
1个回答

58

步骤1:使用SwiftUI视图创建UIHostingController实例

struct ContentView : View {
    var body: some View {
        VStack {
            Text("Test")
            Text("Test2")

        }
    }
}

var child = UIHostingController(rootView: ContentView())

步骤2: 将UIHostingController实例作为子视图控制器添加到任何UIKit视图控制器

var parent = UIViewController()
child.view.translatesAutoresizingMaskIntoConstraints = false
child.view.frame = parent.view.bounds
// First, add the view of the child to the view of the parent
parent.view.addSubview(child.view)
// Then, add the child to the parent
parent.addChild(child)

您可以使用以下代码来移除子控制器 从视图控制器中移除
// Then, remove the child from its parent
child.removeFromParent()

// Finally, remove the child’s view from the parent’s
child.view.removeFromSuperview()

谢谢您的答复,我现在可以在Mac状态栏应用程序中使用SwiftUI了。但是,您是通过父视图设置SwiftUI视图的框架。我想反过来做,有方法吗?并且,只有在没有设置时才会一直为零,这个子视图的框架就像我所理解的那样。 - Faruk
5
谢谢,这个答案很好。我知道苹果公司非常注重“从头开始重写应用程序”和“不要连接任何第三方代码”。但对于地球上的人们来说,如果苹果公司可以将所有的样板代码隐藏起来处理,那就太好了。然后我们就可以逐步将UIView替换为Views。 - William Entriken
16
以上内容没有展示当您想要直接从一个 UIView 使用 SwiftUI View 时会发生什么(即深层次的 UIView 希望使用现有的 SwiftUI 视图,但它没有访问其 UIViewController 的权限)。 - strangetimes
2
@strangetimes,这在SwiftUI中不受支持。你应该考虑重构你的代码,让你的视图可以访问它们的控制器。 - Sam Spencer
3
@Imran,我试图理解为什么需要UIViewController? 通过UIHostingController(rootView: ContentView()).view 你可以“基本上”将SwiftUI视图转换为UIView,一切似乎都能够正常工作,你能提供一下为什么它“不被支持”的原因吗? - user9333301

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接