Realm Swift - SwiftUI 中的集合更改侦听器

问题描述 投票:0回答:1

我在 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
函数,除非不可能。

swift swiftui realm
1个回答
0
投票

我决定使用 Realm 专门为 SwiftUI 创建的内置功能。因此,在每个视图中,哪个 ViewModel 应该具有我实现的 Realm 数据

@ObservedResults(ConversationObject.self) var conversationsObjects

然后使用修饰符将其传递给 ViewModel

.onChange(of: conversationsObjects) { _, updatedConversationsObjects in
    chatViewModel.getConversations(from: updatedConversationsObjects)
}

后来,方法

getConversations
将其从领域对象转换为分配给
@Published var
的其他结构,并且该数据显示在屏幕上

相同的技术分别应用于SettingsObjectsSettingsViewSettingsViewModel。 通过使用这种方法,我能够自动刷新我想要的领域数据。

© www.soinside.com 2019 - 2024. All rights reserved.