如何确保 WidgetKit 视图显示 @FetchRequest 的正确结果?

2023-12-01

我有一个将 Core Data 与 CloudKit 结合使用的应用程序。更改在设备之间同步。主要目标具有后台模式功能,并带有选中的远程通知。主目标和小部件目标都具有相同的应用程序组,并且都具有 iCloud 功能,服务设置为 CloudKit,并且检查了容器中的相同容器。

我的目标是展示actualSwiftUI WidgetKit 视图中的核心数据条目。

我的小部件目标文件:

import WidgetKit
import SwiftUI
import CoreData

// MARK: For Core Data

public extension URL {
    /// Returns a URL for the given app group and database pointing to the sqlite database.
    static func storeURL(for appGroup: String, databaseName: String) -> URL {
        guard let fileContainer = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: appGroup) else {
            fatalError("Shared file container could not be created.")
        }
        
        return fileContainer.appendingPathComponent("\(databaseName).sqlite")
    }
}

var managedObjectContext: NSManagedObjectContext {
    return persistentContainer.viewContext
}

var workingContext: NSManagedObjectContext {
    let context = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType)
    context.parent = managedObjectContext
    return context
}

var persistentContainer: NSPersistentCloudKitContainer = {
    let container = NSPersistentCloudKitContainer(name: "Countdowns")
    
    let storeURL = URL.storeURL(for: "group.app-group-countdowns", databaseName: "Countdowns")
    let description = NSPersistentStoreDescription(url: storeURL)
    
    
    container.loadPersistentStores(completionHandler: { storeDescription, error in
        if let error = error as NSError? {
            print(error)
        }
    })
        
    container.viewContext.automaticallyMergesChangesFromParent = true
    container.viewContext.mergePolicy = NSMergeByPropertyStoreTrumpMergePolicy
    
    return container
}()

// MARK: For Widget

struct Provider: TimelineProvider {
    var moc = managedObjectContext
    
    init(context : NSManagedObjectContext) {
        self.moc = context
    }
    
    func placeholder(in context: Context) -> SimpleEntry {
        return SimpleEntry(date: Date())
    }
    
    func getSnapshot(in context: Context, completion: @escaping (SimpleEntry) -> ()) {
        let entry = SimpleEntry(date: Date())
        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)
            entries.append(entry)
        }
        
        let timeline = Timeline(entries: entries, policy: .atEnd)
        completion(timeline)
    }
}

struct SimpleEntry: TimelineEntry {
    let date: Date
}


struct CountdownsWidgetEntryView : View {
    var entry: Provider.Entry
    
    @FetchRequest(entity: Countdown.entity(), sortDescriptors: []) var countdowns: FetchedResults<Countdown>
    
    var body: some View {
        return (
            VStack {
                ForEach(countdowns, id: \.self) { (memoryItem: Countdown) in
                    Text(memoryItem.title ?? "Default title")
                }.environment(\.managedObjectContext, managedObjectContext)
                Text(entry.date, style: .time)
            }
        )
    }
}

@main
struct CountdownsWidget: Widget {
    let kind: String = "CountdownsWidget"
    
    var body: some WidgetConfiguration {
        StaticConfiguration(kind: kind, provider: Provider(context: managedObjectContext)) { entry in
            CountdownsWidgetEntryView(entry: entry)
                .environment(\.managedObjectContext, managedObjectContext)
        }
        .configurationDisplayName("My Widget")
        .description("This is an example widget.")
    }
}

struct CountdownsWidget_Previews: PreviewProvider {
    static var previews: some View {
        CountdownsWidgetEntryView(entry: SimpleEntry(date: Date()))
            .previewContext(WidgetPreviewContext(family: .systemSmall))
    }
}

但我有一个问题:假设我有 3 个Countdown主应用程序中的记录:

在开始时,小部件视图按预览中的预期显示 3 条记录(用于添加小部件的 UI)。但是当我将小部件添加到主屏幕后,它不显示Countdown行,仅entry.date, style: .time。当时间线条目发生更改时,行也不可见。我制作了一张图片来更好地说明这一点:

adding a widget

Or:

开始时小部件视图按预期显示 3 条记录,但大约一分钟后,如果我删除或添加Countdown主应用程序、小部件中的记录still显示初始 3 个值,但我希望它显示实际值的数量(以反映更改)。时间线entry.date, style .time更改反映在小部件中,但不反映请求中的条目。

有什么方法可以确保我的小部件显示正确的获取请求结果?谢谢。


小部件视图没有observe任何事物。他们只是提供TimelineEntry数据。意思是@FetchRequest, @ObservedObject等等在这里不起作用。


  1. 为您的容器启用远程通知:
let container = NSPersistentContainer(name: "DataModel")
let description = container.persistentStoreDescriptions.first
description?.setOption(true as NSNumber, forKey: NSPersistentStoreRemoteChangeNotificationPostOptionKey)
  1. 更新您的 CoreDataManager 以观察远程通知:
class CoreDataManager {
    var itemCount: Int?

    private var observers = [NSObjectProtocol]()

    init() {
        fetchData()
        observers.append(
            NotificationCenter.default.addObserver(forName: .NSPersistentStoreRemoteChange, object: nil, queue: .main) { _ in
                // make sure you don't call this too often - notifications may be posted in very short time frames
                self.fetchData()
            }
        )
    }

    deinit {
        observers.forEach(NotificationCenter.default.removeObserver)
    }

    func fetchData() {
        let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "Item")

        do {
            self.itemCount = try CoreDataStack.shared.managedObjectContext.count(for: fetchRequest)
            WidgetCenter.shared.reloadAllTimelines()
        } catch {
            print("Failed to fetch: \(error)")
        }
    }
}
  1. 添加另一个字段Entry:
struct SimpleEntry: TimelineEntry {
    let date: Date
    let itemCount: Int?
}
  1. 全部使用在Provider:
struct Provider: TimelineProvider {
    let coreDataManager = CoreDataManager()

    ...

    func getTimeline(in context: Context, completion: @escaping (Timeline<Entry>) -> Void) {
        let entries = [
            SimpleEntry(date: Date(), itemCount: coreDataManager.itemCount),
        ]

        let timeline = Timeline(entries: entries, policy: .never)
        completion(timeline)
    }
}
  1. 现在您可以在视图中显示您的条目:
struct WidgetExtEntryView: View {
    var entry: Provider.Entry

    var body: some View {
        VStack {
            Text(entry.date, style: .time)
            Text("Count: \(String(describing: entry.itemCount))")
        }
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何确保 WidgetKit 视图显示 @FetchRequest 的正确结果? 的相关文章

  • 关于将 Objective C 代码添加到 swift 动态框架的澄清

    我有一个 swift 动态框架 当前正在链接到另一个用 Objective C 编写的框架 这可以工作 但很烦人 因为 Objective C 框架实际上只有 2 个文件 我想知道是否有办法将其带入我的 swift框架 如果这是我会使用的应
  • Swift 中符合协议的泛型类型

    是否可以要求泛型类型的特定实例符合 Swift 中的协议 例如 假设我有一个名为的泛型类型Thing
  • 如何在 iOS 企业帐户中创建开发人员配置文件请求?

    我们有 iOS 企业帐户 现在我们想要向我们的团队添加一名开发人员 该开发人员将创建一个开发人员配置文件 问题是新添加的开发人员在他的苹果帐户中看不到配置文件标签 任何人都知道新添加的开发人员如何创建配置文件 感谢您 Steps 您可以通过
  • 如何使用 AudioKit 音序器设置不在曲目末尾的循环?

    有没有办法在 AKSequencer 中设置具有任意开始和结束时间戳的循环 正如我所看到的 方法 setLoopInfo 只允许您设置循环的末端恰好位于轨道的末尾 但我想在曲目中间设置一个循环 我知道 AudioKit Sequencer
  • 使用仪器分配时 iOS 应用程序冻结

    当我想使用 Instruments Allocation 来分析应用程序的内存使用情况时 它在启动后立即冻结 它总是停留在启动屏幕 这是一个 Xamarin forms 应用程序 这是屏幕截图 其他信息 如果我创建一个新项目 然后使用 In
  • 如何更改 iOS 5 中 UITabBarItem 中文本的颜色

    iOS 5 中有更多外观控制 我们如何更改 UITabBarItem 文本颜色 从默认白色变为其他颜色 编辑 工作解决方案 UITabBarItem appearance setTitleTextAttributes NSDictionar
  • 在 Xamarin 中读取 iOS 的相机权限

    我有一个用 Xamarin 开发的 iOS 应用程序 当应用程序没有访问麦克风的权限时 如果用户尝试从应用程序访问麦克风 我会使用以下命令检查设置AVAudioSession SharedInstance RequestRecordPerm
  • 应用程序关闭时下载报刊亭应用程序

    我正在实现一个报摊杂志应用程序 它通过 Urban Airship 推送通知接收新期刊 只要应用程序位于前台或后台 这就可以正常工作 但据我所知 当应用程序完全关闭时也应该触发下载 但发送推送 content available 1如果我的
  • AUGraph 在 iOS 上是否已被弃用?如果是的话,什么时候?

    我听到过这样的传言AUGraph在 iOS 上已被弃用 例如这篇推特帖子 https twitter com marcoarment status 878323409339338753 marcoarment 您对 atpfm 关于需要重写
  • React-Native 中的导航抽屉

    我是反应原生的新手 不介意我问一个基本问题 我想知道 实现抽屉式导航的分步过程是什么 推荐链接这个链接 https github com react native community react native side menu usage
  • [UITableView _contentOffsetForScrollingToRowAtIndexPath:atScrollPosition:]

    我正在使用表格视图来显示消息 我使用了下面的代码 UIView chatView self bubbleView NSString stringWithFormat message from YES self chatArray addOb
  • 在 Swift 2.0 中以横向模式使用 UIImagePickerController

    我正在编写一个仅限 LandScape 的 iPad 应用程序 我需要从库中拍照以发送数据库 但图像上传屏幕仅适用于纵向模式 如何将其更改为横向模式 我读过一些关于 UIPickerControllerDelegate 不支持横向模式的内容
  • 如何在iOS中获得旋转UIView的完美X,Y位置

    我正在使用 CABasicanimation 来旋转 UIView 我正在使用这段代码 CABasicAnimation rotationAnimation CABasicAnimation animationWithKeyPath tra
  • swift 中 pch 的替代品是什么?

    我想知道可以用什么来代替 swift 中的 pch 有没有 pch 的替代方案或方法可以快速摆脱导入 这样我们就不需要对所有类都这样做 我不想一直随身携带 进口 swift 中 pch 的最佳替代品是什么 您无法在 swift 中定义 宏
  • Gmail 中删除了 iOS 深层链接

    我正在尝试发送一封带有深层链接的电子邮件到我的 iOS 应用程序 使用 myapp 格式从电子邮件中将其打开 它可以在任何 iOS 邮件客户端 邮件 邮箱等 中运行 即点击它打开应用程序 但不能在 Gmail 应用程序 甚至网络 中运行 因
  • 无法为 FacebookSDK 4 构建模块“FBSDKCoreKit”

    我在将 Facebook SDK 3 更新到 4 时遇到问题 当我添加框架时 它已成功添加 但是当我添加头文件时出现错误 无法构建模块 FBSDKCoreKit 不知道原因 在设置中 允许非模块化包含在框架模块中 设置为YES在构建设置中解
  • 为什么 CABasicAnimation 尝试初始化我的自定义 CALayer 的另一个实例?

    我收到此错误 致命错误 对类 MyProject AccordionLayer 使用未实现的初始化程序 init layer 使用以下代码 在我的视图控制器中 override func viewDidLoad let view self
  • 隐藏故事板中的导航栏

    谁能告诉我如何隐藏故事板中的导航栏 我下面的代码在模拟器中运行时工作正常 但它仍然出现在我的故事板中 这真的很烦我 因为它弄乱了我的图像的位置 有人可以帮忙吗 void viewWillAppear BOOL animated super
  • 获取在 iOS UIFont 中追踪字符的路径

    假设我在 iOS 应用程序中使用了自定义字体 Foo 我已将其添加到我的项目 plist 等中 并且我能够渲染UILabels之类的就很好了 现在 如果我想找出可以 追踪 该字体中的字母 P 的点序列 我将如何获得该点序列 例如 假设我想使
  • 如何将 Android 应用程序添加到已在 iOS 应用程序中使用的现有 Firebase 项目?

    我一直在我的 iOS 应用程序中使用 Firebase 项目 我现在想开始为 Android 应用程序使用相同的 Firebase 项目及其所有数据库和存储 在您的应用程序下Overview菜单 你应该按添加另一个应用程序并选择Androi

随机推荐

  • avcodec YUV 转 RGB

    我正在尝试使用 libswscale 将 YUV 帧转换为 RGB 这是我的代码 AVFrame RGBFrame SwsContext ConversionContext ConversionContext sws getCachedCo
  • 从c文件中提取头名称的正则表达式

    如何从包含这样的 c 文件中提取标头 include
  • Grunt、NPM 和 Bower 之间的区别(package.json 与 Bower.json)

    当我想添加一个包 并将依赖项签入 git 时 它属于哪里 进入package json或进入bower json 据我收集的信息 跑步bower install将获取包并将其放入 vendor目录 跑步npm install它会获取它并将其
  • 二叉树递归函数

    我需要打印出一个如下所示的二叉树 x x x x x x x x x x x x x x x xxxxxxxxxxxxxxxx 使用递归打印该行的左侧和右侧 第一行除外 因此该函数将调用带有左起点和右终点参数的显示函数 然后它会调用自己两次
  • Docker:如何从给定容器访问另一个容器中的文件?

    基本上我有一个主目录和图书目录 一般文件结构 还有更多 但这些是重要的部分 因此 当我从 main 向 booksServer 发出请求时 它不起作用 因为节点模块丢失 这是因为节点模块位于 docker 容器内的特定路径 usr src
  • 网络个人资料有什么用?

    我偶然发现了这个项目ASP NET Web 配置文件生成器 为什么我需要代理类来访问配置文件 因为 ASP NET 仅支持带有 网站 选项的开箱即用的配置文件 如果您使用的是 Web 应用程序项目 WAP 那么您必须推出自己的项目 问题源于
  • JAX-RS 未能注入 @EJB 或 @Inject

    我正在尝试测试最小的 JAX RS EJB CDI 注入机制 但目前由于 GlassFish 由于某种原因无法注入而遇到了障碍 使用 Inject 将抛出 NPE 因为 GlassFish 无法注入 POJO 我的 beans xml 仅包
  • 使用 Cerberus 验证两个参数具有相同数量的元素

    有没有办法拥有Cerberus验证两个字段是否具有相同数量的元素 例如 该文档将验证 a 1 2 3 b 4 5 6 这不会 a 1 2 3 b 7 8 到目前为止 我已经想出了这个模式 a required False type list
  • Java Double 初始化为 0.0

    我有一个 bean 其中有一个字段 CustAmount 它是双倍的 我尝试测试该 bean 但我似乎不理解这一点 当我在本地计算机上运行时 它在实例化时初始化为 0 0 当我在 Linux 测试环境中运行相同的代码时 它仍然为空 由于检索
  • 如何在mysql中批量插入插入的id

    我试图使用此查询在 mysql 表中插入多行后获取 insertid insert into sometable id candidateid createdby values 61 3175 1425 60 3175 1425 42 31
  • SQL Server 计算切换间隔秒数

    我有一个这样的表 Value TimeStamp 1 2016 04 01 00 01 09 000 0 2016 04 01 00 01 09 000 0 2016 04 01 00 01 37 000 1 2016 04 01 00 0
  • 了解 VB.NET P/Invoke 声明中的 VBByRefStr

    当尝试使用 C 的 VB NET 程序集中创建的 P Invoke 声明时 我注意到string争论变成ref string论据 仔细检查表明 例如 Public Declare Unicode Function RegDeleteValu
  • 为不同的复合组件指定不同的错误消息

    有没有办法为不同类型的复合组件提供 REQUIRED 消息 我希望能够在消息包中说出以下内容 javax faces component UIInput REQUIRED Please enter a value for 0 com ano
  • 如何在 Clion 和 CMake 中添加 allegro 库?

    我正在尝试使用 Clion IDE 编译我的游戏项目 但在移植 allegro 5 时遇到问题 我收到此错误 main cpp 2 10 fatal error allegro allegro h file not found includ
  • C 中返回数组?

    我无法在 C 中返回数组 我对 C 很陌生 所以我可能会犯一些有趣的错误 这里是 代码 define MAXSIZE 100 int recievedNumbers MAXSIZE void setup put your setup cod
  • 在 Discord.py 中获取用户的邀请总数

    我正在尝试向我的机器人添加一个命令 该命令会回复用户邀请到服务器的总人数 My code if message content startswith invites totalInvites message guild invites aw
  • 谁能解释为什么换行符会使 JavaScript 中的 return 语句未定义? [复制]

    这个问题在这里已经有答案了 这一直是我几个小时痛苦的根源 谁能解释为什么会这样 function x return when there s a line break it doesn t work 2 alert x function y
  • 正则表达式匹配任何字符,包括换行符

    是否有正则表达式来匹配 包括换行符在内的所有字符 例如 在下面的正则表达式中 没有输出 2因为 匹配时不包括新行 string START Curabitur mollis dolor ut rutrum consequat arcu ni
  • 我可以使用 Javascript 将 CSS 样式属性打印到控制台吗?

    还有另一个基本问题 我似乎无法在网上找到答案 我可以使用 javascript 轻松更改元素的 CSS 属性 document getElementById ExampleID style height 30px 但是每当我尝试将属性打印到
  • 如何确保 WidgetKit 视图显示 @FetchRequest 的正确结果?

    我有一个将 Core Data 与 CloudKit 结合使用的应用程序 更改在设备之间同步 主要目标具有后台模式功能 并带有选中的远程通知 主目标和小部件目标都具有相同的应用程序组 并且都具有 iCloud 功能 服务设置为 CloudK