将 AppKit/UIKit 中的 Key-Value Observation 转换为 Combine 和 SwiftUI
Posted
技术标签:
【中文标题】将 AppKit/UIKit 中的 Key-Value Observation 转换为 Combine 和 SwiftUI【英文标题】:Converting Key-Value Observation in AppKit/UIKit to Combine and SwiftUI 【发布时间】:2021-02-14 06:43:09 【问题描述】:我在思考如何在 SwiftUI 中使用 Combine 时遇到了麻烦。我习惯于在 AppKit 和 UIKit 中使用键值观察,因为视图控制器不需要相互了解,只需对一些有助于确定状态的全局对象做出反应。
例如,在 AppKit/UIKit 应用程序中,我会创建一个像这样的全局状态对象:
//Global State file
@objc class AppState: NSObject
@objc dynamic var project: Project?
//Create an instance I can access anywhere in my app
let app = AppState()
然后在视图控制器中,我可以收到有关我的应用范围项目实例的任何更改的通知并做出相应的反应:
//View Controller
class MyViewController: NSViewController
var observerProject: NSKeyValueObservation?
override func viewDidLoad()
observerProject = app.observe(\.project) object, change in
self.refreshData()
func refreshData()
//Query my persistent store and update my UI
Combine/SwiftUI 与此类似的是什么?
我需要创建一个发布者然后监听我的全局对象变化吗?如果是这样,我如何让我的核心数据@FetchRequest
(其谓词包括我的全局Project
对象)实时响应?
我已经用旧方式做事很长时间了,以至于向 SwiftUI/Combine 的过渡让我很困惑。 ????
【问题讨论】:
【参考方案1】:@FetchRequest
不适用于动态谓词(SO 中有一些变通方法),您必须为此使用“老派”NSFetchedResultsController
并将其放入ObservableObject
。这是带有示例的video。这是很多设置和代码。
import SwiftUI
import Combine
class AppState: ObservableObject
static let shared = AppState()
@Published var project: String?
//Just to mimic updates
var count = 0
private init()
//Mimic getting updates to project
Timer.scheduledTimer(withTimeInterval: 2, repeats: true) timer in
print("Timer")
self.project = self.count.description
self.count += 1
if self.count >= 15
timer.invalidate()
class MyViewModel: ObservableObject
@Published var refreshedData: String = "init"
let appState: AppState = AppState.shared
var projectCancellable: AnyCancellable?
init()
projectCancellable = appState.$project.sink(receiveValue:
value in
print(value ?? "nil")
self.refreshData()
)
func refreshData()
refreshedData = Int.random(in: 0...100).description
struct MyView: View
@StateObject var vm: MyViewModel = MyViewModel()
var body: some View
VStack
Text(vm.refreshedData)
struct MyView_Previews: PreviewProvider
static var previews: some View
MyView()
【讨论】:
这非常有帮助。非常感谢你!我认为我缺少的一个重要部分是制作AppState()
的static
实例。以上是关于将 AppKit/UIKit 中的 Key-Value Observation 转换为 Combine 和 SwiftUI的主要内容,如果未能解决你的问题,请参考以下文章