Swift UI - EnvironmentObject 更改不会更新 UI

Posted

技术标签:

【中文标题】Swift UI - EnvironmentObject 更改不会更新 UI【英文标题】:Swift UI - EnvironmentObject change does not update UI 【发布时间】:2019-11-29 16:43:12 【问题描述】:

关于以下问题,我正用头撞桌子。我有一个嵌套的 DataStore(为方便起见),通过 @EnvironmentObject 集成到一个视图中。如果我在 DataStore 中更改某些内容(例如,将新对象放入其中 - 效果很好),UI 不会更新。

在控制台中,我还得到了 print("Object Changed") 的结果,这是由于获取的结果发生了变化。但 UI 仅在我重新启动应用程序后更新。这里有什么问题?

提前非常感谢!

我的测试代码如下所示:

数据存储:

import Foundation
import Combine

class DataStore : ObservableObject
    @Published var documents    = DocumentStore()
    @Published var attachments  = AttachmentStore()


附件商店

//
//  AttachmentStore.swift

import SwiftUI
import Combine
import CoreData

class AttachmentStore: NSObject, ObservableObject 


    // MARK: Private Properties
     let persistenceManager = PersistenceManager()

    private lazy var fetchedResultsController: NSFetchedResultsController<ManagedAttachment> = 
        let fetchRequest: NSFetchRequest<ManagedAttachment> = ManagedAttachment.fetchRequest()
        fetchRequest.sortDescriptors = [NSSortDescriptor(key: "dateCreated", ascending: false)]

        let fetchedResultsController = NSFetchedResultsController(
            fetchRequest: fetchRequest,
            managedObjectContext: self.persistenceManager.managedObjectContext,
            sectionNameKeyPath: nil,
            cacheName: nil)
        fetchedResultsController.delegate = self
        return fetchedResultsController
    ()

    private var attachment: [ManagedAttachment] 
        return fetchedResultsController.fetchedObjects ?? []
    

    // MARK: Public Properties

    @Published var Items : [ManagedAttachment] = []

    public var allItems: [ManagedAttachment] 
        return self.attachment.filter $0 == $0
       

    func setup()
        self.Items = allItems
    
    // MARK: Object Lifecycle

    override init() 
        super.init()
        fetchDocuments()
        setup()
    

    // MARK: Public Methods

    public func allAttachments(for id: UUID) -> [ManagedAttachment]
    
        let attachments = self.allItems.filter $0.parentID == id
        return attachments
    

    public func create(attachment: Attachment) 
        ManagedAttachment.create(object: attachment, in: self.persistenceManager.managedObjectContext)
         saveChanges()
     

    public func delete(attachment: ManagedAttachment)
        persistenceManager.managedObjectContext.delete(attachment)
        self.saveChanges()
    

    public func update()
        self.saveChanges()
    


    // MARK: Private Methods

    private func fetchDocuments() 
        do 
            try fetchedResultsController.performFetch()
            dump(fetchedResultsController.sections)
         catch 
            fatalError()
        
    

    private func saveChanges() 
        guard persistenceManager.managedObjectContext.hasChanges else  return 
        do 
            try persistenceManager.managedObjectContext.save()
            self.objectWillChange.send()
            print("Object Changed")
         catch  fatalError() 
    



extension AttachmentStore: NSFetchedResultsControllerDelegate 
    func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) 
        self.objectWillChange.send()
        print("Object Changed")
    



TestView

import SwiftUI

struct TestView: View 
    @EnvironmentObject var data : DataStore

    var body: some View 
        VStack
            Button(action: 
                self.data.attachments.create(attachment: Attachment(url: "Test"))
            
            ) 
                Text("Add")
            
            // Print the Items in the DataStore
            ForEach(data.attachments.Items, id:\.self)Item in
                Text(Item.url).font(.caption)
            
        

    

【问题讨论】:

看到这个答案:***.com/a/58917498/6570854 究竟是什么不工作?除了setup(),我没有看到你在任何地方改变Items @ribilynn: 非常感谢 - 我修好了。我的问题是我从 attachmentStore 发送了 willChange - 但不是从 datastore 对象发送。非常感谢! 【参考方案1】:

好的,我的问题是我从附件存储区发送了一个 willChange,而不是从数据存储区,所以它没有更新。所以解决办法是手动调用dataStore.objectWillChange.send()。谢谢!

【讨论】:

以上是关于Swift UI - EnvironmentObject 更改不会更新 UI的主要内容,如果未能解决你的问题,请参考以下文章

Swift UI笔记

获得 json 响应后,Swift 4 UI 卡住了

使用 Firebase 观察数据更新 UI (Swift)

swift写UI界面的

Swift 3- 从主线程更新 UI

swift3 - 使用后台数据更新 ui