SwiftUI-混合开发

524 阅读1分钟

介绍

混合开发主要是指在 SwiftUI 中使用 UIKit(SwiftUI 中使用 UIView 与 UIViewController)与在 UIKit 中使用 SwiftUI。通过混合开发,开发者可以更灵活地利用 SwiftUI 与 UIKit 的各自优势,开发出功能强大且具有良好用户体验的应用程序。

UIKit in SwiftUI

Apple 针对 UIView 与 UIViewController 提供了两个 “表示器”,如下表所示。通过这两个表示器可以很容易地将它们转换成 SwiftUI 里面的 View。

UIKitSwiftUI
UIViewUIViewRepresentable
UIViewControllerUIViewControllerRepresentable

UIView in SwiftUI

UIViewRepresentable

  • 要使 UIView 在 SwiftUI 中可用,需要用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)
    }
}

UIViewController in SwiftUI

UIViewControllerRepresentable

  • 要使 UIViewController 在 SwiftUI 中可用,需要用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")
    }
}

SwiftUI in UIKit

UIKit 中使用 SwiftUI,需要通过UIHostingController包装 View,然后才能使用。

// 可以是复杂的ContentView
let vc = UIHostingController(rootView: ContentView())
// 也可以是简单的Text等其他View
let vc = UIHostingController(rootView: Text("Hello SwiftUI"))