KMP 学习之Compose 视图是怎么添加到swiftUI中的

97 阅读1分钟

以下代码取自 Compose demo 中的Imageviewer

struct ContentView: View {
    var body: some View {
        ZStack {
            ComposeView()
                    .ignoresSafeArea(.all) // Compose has own keyboard handler
            VStack {
                gradient.ignoresSafeArea(edges: .top).frame(height: 0)
                Spacer()
            }
        }.preferredColorScheme(.dark)
    }
}

struct ComposeView: UIViewControllerRepresentable {
    func makeUIViewController(context: Context) -> UIViewController {
        let controller = Main_iosKt.MainViewController()
        controller.overrideUserInterfaceStyle = .light
        return controller
    }

    func updateUIViewController(_ uiViewController: UIViewController, context: Context) {
    }
    
}

这里先介绍一下 UIViewControllerRepresentable

UIViewControllerRepresentableSwiftUI 提供的一个协议,用于把 UIKitUIViewController 控件包装成 SwiftUI 可以使用的视图。这样你就可以在 SwiftUI 界面中直接嵌入和复用原有的 UIKit 控件,比如图片选择器、地图、相机等。

使用方法是:

1. 创建一个结构体,遵循 UIViewControllerRepresentable 协议。
2. 实现两个必须的方法:
   - makeUIViewController(context:) :创建并返回你的 UIKit 控件实例。
   - updateUIViewController(_:context:) :当 SwiftUI 状态变化时,用于同步更新 UIKit 控件。

示例:

struct MyControllerWrapper: UIViewControllerRepresentable {
    func makeUIViewController(context: Context) -> MyViewController {
        MyViewController()
    }
    func updateUIViewController(_ uiViewController: MyViewController, context: Context) {
        // 这里可以根据需要更新 UI
    }
}

跟UIViewControllerRepresentable 类似的还有 UIViewRepresentable 用来处理UIView的

示例:

struct MyLabel: UIViewRepresentable {
    func makeUIView(context: Context) -> UILabel {
        let label = UILabel()
        label.text = "Hello, UIKit!"
        return label
    }
    func updateUIView(_ uiView: UILabel, context: Context) {
        // 更新逻辑
    }
}

所以ComposeView 就是使用 UIViewControllerRepresentable 把Compose视图包装到了 MainViewController(UIViewController)中 然后添加到SwiftUI中。

MainViewController 又是什么呢?

MainViewController 是在shared-iosMain下面的一个kotlin文件定义的一个方法,这个方法返回的就是UIViewController对应ios的UIViewController。

fun MainViewController(): UIViewController =
    ComposeUIViewController {
        ImageViewerIos()
    }

ImageViewerIos() 就是我们自己写的Compose视图。

image.png