Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Swift 当主机应用程序关闭时,如何在小部件iOS 14中重新加载从CoreData获取数据_Swift_Core Data_Swiftui_Widgetkit - Fatal编程技术网

Swift 当主机应用程序关闭时,如何在小部件iOS 14中重新加载从CoreData获取数据

Swift 当主机应用程序关闭时,如何在小部件iOS 14中重新加载从CoreData获取数据,swift,core-data,swiftui,widgetkit,Swift,Core Data,Swiftui,Widgetkit,我目前正在使用SwiftUI开发一个应用程序 我想从小部件中的CoreData重新加载数据,以便在每次关闭主机应用程序时更新较新的数据 但在我的代码中,数据不会被重新加载 我怎样才能解决这个问题 TimerApp.swift(主机应用程序) TimerWidget.swift(小部件扩展) Xcode:12.0.1版 iOS:14.0 生命周期:SwiftUI应用程序负责获取数据的代码仅在init中: struct Provider: TimelineProvider { var m

我目前正在使用SwiftUI开发一个应用程序

我想从
小部件中的
CoreData
重新加载数据,以便在每次关闭主机应用程序时更新较新的数据

但在我的代码中,数据不会被重新加载

我怎样才能解决这个问题


TimerApp.swift(主机应用程序)

TimerWidget.swift(小部件扩展)


Xcode:12.0.1版

iOS:14.0


生命周期:SwiftUI应用程序

负责获取数据的代码仅在
init
中:

struct Provider: TimelineProvider {
    var moc = PersistenceController.shared.managedObjectContext
    var timerEntity:TimerEntity?
    
    init(context : NSManagedObjectContext) {
        self.moc = context
        let request = NSFetchRequest<TimerEntity>(entityName: "TimerEntity")
        
        do{
            let result = try moc.fetch(request)
            timerEntity = result.first
        }
        catch let error as NSError{
            print("Could not fetch.\(error.userInfo)")
        }
    }
    ...
}

注意:我建议在
WidgetCenter.shared.reloadAllTimelines()
周围添加一些保护措施,以确保不经常刷新它。

感谢您的回答,尽管我根据您的回答更改了代码,但提取数据从未更新过。。。我看不到数据更新过一次。只有在我构建项目时,
小部件中的数据才会更新。@Tio我更新了我的答案,基本上你也需要在
getTimeline
中重新加载
timerenty
(不仅仅是在init中)。谢谢你更新你的答案,我试着按照你的建议更改了我的代码。但是我的代码不起作用,出现了一些错误。我更新了我的问题,您是否介意建议我如何在
getTimeline
函数中更改代码以执行
NSFetchRequest
?最后,我还可以在
getTimeline
函数中重新加载执行
NSFetchRequest
的数据。
import WidgetKit
import SwiftUI
import CoreData

struct Provider: TimelineProvider {
    
    var moc = PersistenceController.shared.managedObjectContext
    var timerEntity:TimerEntity?
    
    init(context : NSManagedObjectContext) {
        self.moc = context
        let request = NSFetchRequest<TimerEntity>(entityName: "TimerEntity")
        
        do{
            let result = try moc.fetch(request)
            timerEntity = result.first
        }
        catch let error as NSError{
            print("Could not fetch.\(error.userInfo)")
        }
    }
    
    func placeholder(in context: Context) -> SimpleEntry {
        return SimpleEntry(date: Date(), timerEntity: timerEntity!)
    }
    
    func getSnapshot(in context: Context, completion: @escaping (SimpleEntry) -> ()) {
        let entry = SimpleEntry(date: Date(), timerEntity: timerEntity!)
        return completion(entry)
    }
    
    func getTimeline(in context: Context, completion: @escaping (Timeline<Entry>) -> ()) {
        var entries: [SimpleEntry] = []
        
        let currentDate = Date()
        for hourOffset in 0 ..< 5 {
            let entryDate = Calendar.current.date(byAdding: .minute, value: hourOffset, to: currentDate)!
            let entry = SimpleEntry(date: entryDate, timerEntity: timerEntity!)
            entries.append(entry)
        }
        
        let timeline = Timeline(entries: entries, policy: .atEnd)
        completion(timeline)
    }
}

struct SimpleEntry: TimelineEntry {
    let date: Date
    let timerEntity:TimerEntity
}

struct TimerWidgetEntryView : View {
        
    var entry: Provider.Entry
    
    var body: some View {
        return (
            VStack{
                Text(entry.timerEntity.task ?? "")
            }
        )
    }
}

@main
struct TimerWidget: Widget {
    let kind: String = "TimerWidget"
    
    var body: some WidgetConfiguration {
        StaticConfiguration(kind: kind, provider: Provider(context: PersistenceController.shared.managedObjectContext)) { entry in
            TimerWidgetEntryView(entry: entry)
                .environment(\.managedObjectContext, PersistenceController.shared.managedObjectContext)
        }
    }
}
struct Provider: TimelineProvider {
    
    var moc = PersistenceController.shared.managedObjectContext
    @State var timerEntity:TimerEntity?
    
    init(context : NSManagedObjectContext) {
        self.moc = context
        let request = NSFetchRequest<TimerEntity>(entityName: "TimerEntity")
        
        do{
            let result = try moc.fetch(request)
            timerEntity = result.first
        }
        catch let error as NSError{
            print("Could not fetch.\(error.userInfo)")
        }
    }
    
    func placeholder(in context: Context) -> SimpleEntry {
        return SimpleEntry(date: Date(), timerEntity: timerEntity ?? TimerEntity())
    }
    
    func getSnapshot(in context: Context, completion: @escaping (SimpleEntry) -> ()) {
        let entry = SimpleEntry(date: Date(), timerEntity: timerEntity!)
        return completion(entry)
    }
    
    func getTimeline(in context: Context, completion: @escaping (Timeline<Entry>) -> ()) {
        var entries: [SimpleEntry] = []
        let currentDate = Date()
        
        let request = NSFetchRequest<TimerEntity>(entityName: "TimerEntity")
        do{
            let result = try moc.fetch(request)
            timerEntity = result.first
        }
        catch let error as NSError{
            print("Could not fetch.\(error.userInfo)")
        }
        
        for hourOffset in 0 ..< 5 {
            let entryDate = Calendar.current.date(byAdding: .minute, value: hourOffset, to: currentDate)!
            let entry = SimpleEntry(date: entryDate, timerEntity: timerEntity ?? TimerEntity())
            entries.append(entry)
        }
        
        let timeline = Timeline(entries: entries, policy: .atEnd)
        completion(timeline)
    }
}
struct Provider: TimelineProvider {
    var moc = PersistenceController.shared.managedObjectContext
    var timerEntity:TimerEntity?
    
    init(context : NSManagedObjectContext) {
        self.moc = context
        let request = NSFetchRequest<TimerEntity>(entityName: "TimerEntity")
        
        do{
            let result = try moc.fetch(request)
            timerEntity = result.first
        }
        catch let error as NSError{
            print("Could not fetch.\(error.userInfo)")
        }
    }
    ...
}
.onChange(of: scenePhase) { newScenePhase in
    if newScenePhase == .background {
        WidgetCenter.shared.reloadAllTimelines()
    }
}