我在 SwiftUI 项目中使用 Realm 来存储一些数据。 目前我存储有
ConversationObject
和 SettingObject
类型。
每个对象都有其对应的Repository
(例如 ConversationsRepository):
final class ConversationsRepository: ConversationsRepositoryProtocol {
@Inject private var realmManager: RealmManaging
init() {}
func getConversations() -> AnyPublisher<[Conversation], Error> {
realmManager.objects(ofType: ConversationObject.self)
.map { $0.map({ $0.toModel }) }
.eraseToAnyPublisher()
}
[...]
}
利用
generic RealmManager
class RealmManager: RealmManaging {
let realm = try? Realm()
private let realmQueue: DispatchQueue = DispatchQueue(label: "realmQueue")
private let updatePolicy: Realm.UpdatePolicy = .modified
private enum RealmError: Error {
case realmConstructionError
}
private init() {}
static let shared: RealmManaging = {
RealmManager()
}()
func objects<T: Object>(ofType: T.Type) -> AnyPublisher<[T], Error> {
Future { promise in
self.realmQueue.async {
do {
let realm = try Realm()
if realm.isInWriteTransaction || realm.isPerformingAsynchronousWriteOperations {
try realm.commitWrite()
}
let objects = realm.objects(T.self)
promise(Result.success(objects.compactMap { $0 }))
} catch {
promise(Result.failure(error))
}
}
}
.eraseToAnyPublisher()
}
[...]
}
在我的项目中每个视图
struct ChatView: View {
@StateObject private var chatViewModel: ChatViewModel = ChatViewModel()
[...]
}
它的 ViewModel 管理存储库数据并将其传递给相应的视图
final class ChatViewModel: ObservableObject {
@Inject private var conversationsRepository: ConversationsRepositoryProtocol
@Published var currentConversation: Conversation?
@Published var conversations: [Conversation] = []
private var cancelBag: Set<AnyCancellable> = Set<AnyCancellable>()
init() {
fetchConversations()
}
func fetchConversations() {
conversationsRepository.getConversations()
.receive(on: DispatchQueue.main)
.sink { _ in
} receiveValue: { [weak self] fetchedConversations in
guard let self = self,
!fetchedConversations.isEmpty else {
self?.addNewConversation()
return
}
self.conversations = fetchedConversations
self.sortConversations()
self.currentConversation = self.conversations.last
}
.store(in: &cancelBag)
}
}
我的问题是我有 ChatView,它显示
ConversationObject collection
的数据,但我有 SettingsView,我可以在其中删除所有 ConversationObjects
。两个视图的视图模型都使用 ConversationRepository
来完成它们的工作。但是当我删除 SettingsView中的
ConversationObject
数据时,我希望重新加载 ChatViewModel 中的数据
我想创建可以在各种 ViewModels 中使用的观察者,以便它们可以拥有我的 Realm 集合的最新数据并对改变其视图的更改做出反应。 我知道我可以简单地在我的 ViewModels 中使用 Realm 对象 并在那里创建
Realm Notification Token
,但我想避免在我的 ViewModel 中显式使用 Realm 对象,宁愿通过调用一些存储库函数来间接执行稍后调用通用 RealmManager
函数,除非不可能。
我决定使用 Realm 专门为 SwiftUI 创建的内置功能。因此,在每个视图中,哪个 ViewModel 应该具有我实现的 Realm 数据
@ObservedResults(ConversationObject.self) var conversationsObjects
然后使用修饰符将其传递给 ViewModel
.onChange(of: conversationsObjects) { _, updatedConversationsObjects in
chatViewModel.getConversations(from: updatedConversationsObjects)
}
后来,方法
getConversations
将其从领域对象转换为分配给@Published var
的其他结构,并且该数据显示在屏幕上
相同的技术分别应用于SettingsObjects、SettingsView和SettingsViewModel。 通过使用这种方法,我能够自动刷新我想要的领域数据。