混合开发主要是指在 SwiftUI 中使用 UIKit(SwiftUI 中使用 UIView 与 UIViewController)与在 UIKit 中使用 SwiftUI。通过混合开发,开发者可以更灵活地利用 SwiftUI 与 UIKit 的各自优势,开发出功能强大且具有良好用户体验的应用程序。
Apple 针对 UIView 与 UIViewController 提供了两个 “表示器”,如下表所示。通过这两个表示器可以很容易地将它们转换成 SwiftUI 里面的 View。
UIKit | SwiftUI |
---|---|
UIView | UIViewRepresentable |
UIViewController | UIViewControllerRepresentable |
UIViewRepresentable
对 UIView 进行包装。UIViewRepresentable
中主要有 2 个方法需要实现。 makeUIView()
:创建View
。updateUIView()
:根据条件与业务逻辑设置View
的状态。使用 UIKit 中的UIActivityIndicatorView
。
import SwiftUI
import UIKit
struct ActivityIndicator: UIViewRepresentable {
var isAnimating: Bool
// 如下的2个方法都是与UIKit相关
func makeUIView(context: Context) -> UIActivityIndicatorView {
let v = UIActivityIndicatorView()
v.color = .orange
return v
}
func updateUIView(_ uiView: UIActivityIndicatorView, context: Context) {
if isAnimating {
uiView.startAnimating()
} else {
uiView.stopAnimating()
}
}
}
struct ContentView: View {
var isAnimating = true
var body: some View {
ActivityIndicator(isAnimating: isAnimating)
}
}
UIViewControllerRepresentable
对 UIViewController 进行包装。UIViewControllerRepresentable
中主要有 2 个方法需要实现。 makeUIViewController()
:创建UIViewController
。updateUIViewController()
:根据条件与业务逻辑设置UIViewController
的状态。使用 UIKit 中的UINavigationController
。
import SwiftUI
import UIKit
struct NavigationViewController: UIViewControllerRepresentable {
var vc: UIViewController
var title: String
func makeUIViewController(context: Context) -> UINavigationController {
let nvc = UINavigationController(rootViewController: vc)
return nvc
}
func updateUIViewController(_ navigationController: UINavigationController, context: Context) {
navigationController.viewControllers[0].title = title
}
}
struct ContentView: View {
var body: some View {
NavigationViewController(vc: UIViewController(), title: "UIViewControllerRepresentable")
}
}
UIKit 中使用 SwiftUI,需要通过UIHostingController
包装 View,然后才能使用。
// 可以是复杂的ContentView
let vc = UIHostingController(rootView: ContentView())
// 也可以是简单的Text等其他View
let vc = UIHostingController(rootView: Text("Hello SwiftUI"))