Core data 将AppKit/UIKit中的键值观察值转换为Combine和SwiftUI
我很难理解如何在SwiftUI中使用联合收割机。我习惯于在AppKit和UIKit中使用键值观察,因为视图控制器不需要相互了解,只需要对一些帮助确定状态的全局对象作出反应 例如,在AppKit/UIKit应用程序中,我会创建一个全局状态对象,如下所示:Core data 将AppKit/UIKit中的键值观察值转换为Combine和SwiftUI,core-data,swiftui,key-value-observing,combine,Core Data,Swiftui,Key Value Observing,Combine,我很难理解如何在SwiftUI中使用联合收割机。我习惯于在AppKit和UIKit中使用键值观察,因为视图控制器不需要相互了解,只需要对一些帮助确定状态的全局对象作出反应 例如,在AppKit/UIKit应用程序中,我会创建一个全局状态对象,如下所示: //Global State file @objc class AppState: NSObject { @objc dynamic var project: Project? } //Create an instance I can ac
//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
}
}
联合收割机/SwiftUI对此的模拟是什么
我是否需要创建发布者,然后侦听全局对象更改?如果是这样,我如何使我的核心数据@FetchRequest
(其谓词包括我的全局项目
对象)实时响应
我已经用老方法做了很长时间了,这种到SwiftUI/Combine的转换让我相当困惑
@FetchRequest
不能很好地处理动态谓词(SO中有一些解决方法),为此,您必须使用“旧式”NSFetchedResultsController
,并将其放入一个observeObject
中。这是一本附有样品的书。这需要大量的设置和代码
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
实例。