这是我对解决这个问题的看法。我的应用面向 iOS 14 或更高版本:
当前状态
我有一个 Main.storyboard 文件,其中一个视图控制器场景设置为具有自定义类 ViewController 的初始视图控制器。这是自定义类的实现:
import UIKit
class ViewController: UIViewController {
@IBOutlet var label: UILabel!
}
目标
在 SwiftUI 应用程序生命周期中使用此类并使其对@EnvironmentObject 实例做出反应和交互(在这种情况下,我们称之为主题管理器)。
解决方案
我将定义一个带有Theme 已发布属性的ThemeManager 可观察对象,如下所示:
import SwiftUI
class ThemeManager: ObservableObject {
@Published var theme = Theme.purple
}
struct Theme {
let labelColor: Color
}
extension Theme {
static let purple = Theme(labelColor: .purple)
static let green = Theme(labelColor: .green)
}
extension Theme: Equatable {}
接下来,我创建了一个 ViewControllerRepresentation 以便能够在 SwiftUI 中使用 ViewController:
import SwiftUI
struct ViewControllerRepresentation: UIViewControllerRepresentable {
@EnvironmentObject var themeManager: ThemeManager
// Use this function to pass the @EnvironmentObject to the view controller
// so that you can change its properties from inside the view controller scope.
func makeUIViewController(context: Context) -> ViewController {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let viewController = storyboard.instantiateInitialViewController { coder in
ViewController(themeManager: themeManager, coder: coder)
}
return viewController!
}
// Use this function to update the view controller when the @EnvironmentObject changes.
// In this case I modify the label color based on the themeManager.
func updateUIViewController(_ uiViewController: ViewController, context: Context) {
uiViewController.label.textColor = UIColor(themeManager.theme.labelColor)
}
}
然后我更新了ViewController 以接受themeManager 实例:
import UIKit
class ViewController: UIViewController {
@IBOutlet var label: UILabel!
let themeManager: ThemeManager
init?(themeManager: ThemeManager, coder: NSCoder) {
self.themeManager = themeManager
super.init(coder: coder)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
@IBAction func toggleTheme(_ sender: UIButton) {
if themeManager.theme == .purple {
themeManager.theme = .green
} else {
themeManager.theme = .purple
}
}
}
现在,要做的最后一件事是创建主题管理器的实例并将其作为环境对象传递给视图控制器表示:
import SwiftUI
@main
struct ThemeEnvironmentApp: App {
@StateObject private var themeManager = ThemeManager()
var body: some Scene {
WindowGroup {
ViewControllerRepresentation()
.environmentObject(themeManager)
}
}
}
运行应用程序会显示带有标签和按钮的视图控制器。点击按钮会触发IBAction,这会更改themeManager.theme,从而触发对表示的updateUIViewController(_:, context:)的调用: