【问题标题】:Changes when record was created in today extension and updated in app are not visible in today extension在今天的扩展程序中创建记录并在应用程序中更新时的更改在今天的扩展程序中不可见
【发布时间】:2017-05-20 11:55:09
【问题描述】:

只是我有一个应用程序和今天的扩展程序。我还有两个实体:GoalService

@objc(Goal)
class Goal: NSManagedObject {

    @NSManaged var identifier: String
    @NSManaged var startDate: Date
    @NSManaged var endDate: Date

    private var services: [Service] {
    
        let predicate = NSPredicate(format: "date >= %@ && date <= %@", startDate as NSDate, endDate as NSDate)

        return Service.mr_findAll(with: predicate) as! [Service]
    }

    var duration: Int64 {
        return services.reduce(0) { $0 + $1.duration }
    }
}

当我在今日扩展程序中创建与goal 相关的service 并在应用程序中更新它时,更新的结果在今日扩展程序中不可见,而在应用程序中正确显示。为什么?

这是我在扩展或扩展中创建和更新记录的方式:

MagicalRecord.save({ context in
        
    Service.createOrUpdate(withDuration: duration, date: Date(), identifier: identifier, in: context)
        
}, completion: { _, error in
        
        //do something on completion
})

【问题讨论】:

  • 你能提供你执行更改的代码吗?还有你为什么用NSManagedObjectContext.mr_default().fetch(fetchRequest)而不是self.managedObjectContext.fetch(fetchRequest)
  • 我应该使用 self 吗?总是相同的上下文?
  • 恕我直言,您应该使用 self 但我无法 100% 判断,因为我不知道您如何使用此类。上下文不一定必须相同,如果是,则没问题,但在某些情况下,应用程序甚至可能崩溃。
  • 好的,我稍后会告诉你...我如何进行更改...

标签: ios swift core-data magicalrecord


【解决方案1】:

扩展程序和应用程序是共享某些相同代码的不同程序。所以两者都在创建自己的自己的 persistentStoreCoordinator 和上下文。

通常在同一个应用程序中,您将有多个上下文都附加到同一个 persistentStoreCoordinator 并且其中一个的更改将由通过 notificationCenter 发送然后合并的通知处理。在这种情况下,有两个问题 - 1)notificationCenter 在应用程序和扩展程序之间不共享,因此它们无法轻松通信;2)上下文不共享相同的persistentStoreCoordinator,因此您不能使用“mergeChangesFromContextDidSaveNotification”即使您确实传递了该信息。

我以前没有尝试过,但这是我会尝试的:

  1. 设置某种方式来触发发生的更改。有很多解决方案。
  2. 将您的 managedObjectContext(s) 设置为 0 的 stalenessInterval
  3. 当发生变化时,您必须更新您的核心数据。您可以通过在所有核心数据对象上调用refreshObject:mergeChanges: 来完成此操作,或者进行另一次提取。诀窍是,您必须从存储中获取上下文,并从文件中获取存储,并且不能命中中间的任何缓存。

【讨论】:

  • 我知道应用程序和扩展程序是完全独立的应用程序。但是数据库是在它们之间共享的。现在我在应用扩展中创建实体,然后在应用中更新它(应用可以通过扩展看到刚刚创建的实体)。但是应用程序所做的更改对扩展程序不可见。为什么?我究竟应该怎么做才能解决这个问题?更新记录后,我确实在应用程序中调用了refreshObject:mergeChanges,但它没有用。我不明白managedObjectContextstalenessInterval。我应该在哪里设置?
  • 好的,我做到了。我刚刚取了对象。刷新它们,然后再次获取。它奏效了。
  • 谢谢。明天我会为你奖励赏金:)
【解决方案2】:

基于@JonRose 回答我的问题的最终解决方案是:

获取我感兴趣的记录,在我从中获取它们的相同上下文中刷新它们,然后再次获取它们:

private var services: [Service] {

    let predicate = NSPredicate(format: "date >= %@ && date <= %@", startDate as NSDate, endDate as NSDate)

    for service in Service.mr_findAll(with: predicate, in: NSManagedObjectContext.mr_rootSaving())! {
        NSManagedObjectContext.mr_rootSaving().refresh(service, mergeChanges: false)
    }

    return Service.mr_findAll(with: predicate) as! [Service]
}

【讨论】:

  • 在从 SiriKit 添加项目时尝试在我的主应用程序上重新加载数据时偶然发现了同样的问题。最后我需要再次获取并刷新。有趣的是,仅一次获取或一次刷新不会获取通过 SiriKit 执行的更改!这似乎是一个相当的黑客。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多