我有这样的发布者:发布userId
时会加载用户 NSManagedObject
userIdPublisher
.combineLatest(companyPublisher)
.flatMap{ (userId, _) in
self.userRepo.loadUser(userId)
}
.map { $0 }
.receive(on: DispatchQueue.main)
.sink(receiveCompletion: { completion in
self.user = nil
}, receiveValue: { user in
self.user = user
})
.store(in: &disposables)
我将其分配给ObservableObject上的 @Published 用户变量
但是当我为了获得user.company.id而访问它时,它为零。
在接收器上的调试器断点上,通常具有参考user.company并填充其字段 但是在View中通常有user.company引用nil,有时我可以访问user的字段,但有时它们是nil
其余代码示例:
SwiftUI视图
CompanyView(companyId: self.settings.user?.company?.id ?? "")
此处正在加载代码:
func load(id: String) -> Future<ManagedObject, Error> {
Future { promise in
self.storage.persistentContainer.performBackgroundTask { [weak self] context in
guard let self = self else { return }
let request = ManagedObject.fetchRequest() as! NSFetchRequest<ManagedObject>
request.predicate = NSPredicate(format: "id = %@", id)
do {
let result = try context.fetch(request)
if let object = result.last {
guard result.count == 1 else { promise(.failure(CoreDataError.inconsistentState)) ; return }
//promise(.success(self.decode(object: object)))
promise(.success(object))
} else {
promise(.failure(CoreDataError.notFound))
}
} catch {
promise(.failure(CoreDataError.readError(error)))
}
}
}
}
如果我替换了Publisher的flatMap代码以直接使用NSFetchRequest和mainContext又称为viewContext,它似乎可以正常工作。
userIdPublisher
.combineLatest(companyPublisher)
.flatMap{ (userId, _) in
Future { promise in
let request : NSFetchRequest<User> = User.fetchRequest()
request.predicate = NSPredicate(format: "id = %@", userId)
do {
let result = try CoreDataStorage.shared.mainContext.fetch(request)
promise(.success(result.last!))
} catch {
promise(.failure(CoreDataError.notFound))
}
}
}
.map { $0 }
.receive(on: DispatchQueue.main)
.sink(receiveCompletion: { completion in
self.user = nil
}, receiveValue: { user in
self.user = user
})
.store(in: &disposables)
所以可能的问题是我正在用performBackgroundTask { context
受管理对象无法在视图/用户界面中使用。所以我应该有单独的方法。通常在SwiftUI视图中,我使用@FetchedRequest,它可以正常工作。我认为我在这里也应该转向它,但是很难为userId传递参数。我认为只能通过init(userId :)