混合开发主要是指在 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"))