【问题标题】:View not being updated when ViewModel gets new dataViewModel 获取新数据时视图未更新
【发布时间】:2020-12-31 15:41:24
【问题描述】:

我有一个应用程序会每天调用一次 API 来检索新数据。

应用启动时会检查是否有新数据可用,将新数据保存到核心数据,调用核心数据在视图中显示数据。

问题
将新数据保存到核心数据后,我的视图将不会显示新保存的数据,而是显示我模型中的默认虚拟数据。重新启动应用后将显示新数据。

问题
如何在视图中显示新保存的数据而无需重新启动应用程序?我正在使用 MVVM 模式。下面是我的代码,其中包含指向我的代码的链接。

UVIndexNowModel

class UVIndexNowModel: ObservableObject
{
    @Published var uvIndex: Int
    @Published var dateTime: Date
    
    init(uvIndex: Int = 0, dateTime: Date = Date())
    {
        self.uvIndex = uvIndex
        self.dateTime = dateTime
    }
}

UVIndexNowViewModel

class UVIndexNowViewModel: NSObject, ObservableObject
{
    private var isFirstAppearance = true
    private let moc = PersistentStore.shared.context
    private let nowController: NSFetchedResultsController<UVHour>
    
    @Published var data: UVIndexNowModel = UVIndexNowModel()
    @Published var coreDateError: Bool = false
    
    override init()
    {
        nowController = NSFetchedResultsController(fetchRequest: UVHour.uvIndexNowRequest,
                                                   managedObjectContext: moc,
                                                   sectionNameKeyPath: nil, cacheName: nil)
        
        super.init()
        
        nowController.delegate = self
        
        do {
            try nowController.performFetch()
            let results = nowController.fetchedObjects ?? []
            
            setUVIndex(from: results)
            
        } catch {
            print("failed to fetch items!")
        }
    }
    
    func setUVIndex(from hours: [UVHour])
    {
        let date = Date()
        let formatter = DateFormatter()
        formatter.timeZone = .current
        formatter.dateFormat = "MMM/d/yyyy hh a"

        let todaystr = formatter.string(from: date)
        
        print("UVIndexNowVM.setUVIndex() size of UVHour array: \(hours.count)")
        
        for i in hours
        {
            let tempDateStr = formatter.string(from: i.wrappedDateTime)

            if todaystr == tempDateStr
            {
                print("UV Now VM Date matches! \(tempDateStr)")
                
                self.data.uvIndex = i.wrappedUVIndex
                self.data.dateTime = i.wrappedDateTime
                break
            }
        }
    }
    
}

extension UVIndexNowViewModel: NSFetchedResultsControllerDelegate
{
    func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>)
    {
        print("UVIndexNowViewModel controllerDidChangeContent was called. New Stuff in DB")
        guard let results = controller.fetchedObjects as? [UVHour] else { return }
        
        setUVIndex(from: results)
    }
}

UVIndexNowView

struct UVIndexNowView: View {
    @ObservedObject var vm = UVIndexNowViewModel()
    
    var body: some View {
        VStack {
            Text("\(vm.data.dateTime)")
            Text("UV Index: \(vm.data.uvIndex)")
        }
    }
}

【问题讨论】:

    标签: ios swift core-data mvvm swiftui


    【解决方案1】:

    由于您的UVIndexNowModelObservableObject,您需要在单独的视图中观察它,例如

    struct UVIndexNowView: View {
        @ObservedObject var vm = UVIndexNowViewModel()
        
        var body: some View {
           UVIndexNowDataView(data: vm.data)    // << here !!
        }
    }
    

    struct UVIndexNowDataView: View {
        @ObservedObject var data: UVIndexNowModel
        
        var body: some View {
            VStack {
                Text("\(data.dateTime)")
                Text("UV Index: \(data.uvIndex)")
            }
        }
    }
    

    【讨论】:

    • 我应该使用Binding,因为事实的来源会存储在不同的视图中吗?
    • 不,你使用引用类型模型,它本质上已经引用了事实来源。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-28
    • 2019-09-16
    • 2017-09-27
    • 1970-01-01
    相关资源
    最近更新 更多