应用程序可以调入扩展所做的核心数据更改吗?

时间:2018-07-10 09:43:11

标签: ios swift core-data

我正在开发一个在自身和Notification Service Extension之间使用共享Core Data数据库的应用程序。应用程序和扩展都能够读取和写入相同的Core Data数据库。

但是,一旦数据库中的相应字段发生更改,应用程序就需要更新显示的信息。有没有一种有效的方法来通知扩展对该数据库所做的更改?我假设应用程序和扩展使用不同的托管上下文来访问数据库。还是我错了?

2 个答案:

答案 0 :(得分:1)

使用SwiftEventBus这很简单

Controller.swift

let yourObj = YourObject()

SwiftEventBus.post("EventName", sender: yourObj)

Extension.swift

let yourObj = YourObject()

SwiftEventBus.post("EventName", sender: yourObj)

AppDelegate.swift

SwiftEventBus.onMainThread(self, name: "EventName") { (result) in
    if let yourObject = result.object as? YourObject {
        // Queue or write the data as per your need
    }
}

答案 1 :(得分:0)

我指出@CerlinBoss使用通知后,发现了解决的问题的解决方案。可以从扩展名向应用程序发送通知(反之亦然)。这可以在iOS中使用Darwin通知中心来完成。但是,限制是您不能使用通知将自定义数据发送到您的应用程序。

阅读了许多文章后,我决定避免通过两个不同的过程并使用多个托管上下文对Core Data数据库进行更改。相反,我将需要传达给应用程序的数据放入UserDefaults的一个键中,一旦通知应用程序更改,我便将它们出队并更新Core Data上下文。

公用代码

Swift 4.1

import os
import Foundation

open class UserDefaultsManager {

  // MARK: - Properties

  static let applicationGroupName = "group.com.organization.Application"

  // MARK: - Alert Queue Functions

  public static func queue(notification: [AnyHashable : Any]) {
    guard let userDefaults = UserDefaults(suiteName: applicationGroupName) else {
      return
    }
    // Retrieve the already queued notifications.
    var alerts = [[AnyHashable : Any]]()
    if let data = userDefaults.data(forKey: "Notifications"),
      let items = NSKeyedUnarchiver.unarchiveObject(with: data) as? [[AnyHashable : Any]] {
      alerts.append(contentsOf: items)
    }
    // Add the new notification to the queue.
    alerts.append(notification)
    // Re-archive the new queue.
    let data = NSKeyedArchiver.archivedData(withRootObject: alerts)
    userDefaults.set(data, forKey: "Notifications")
  }

  public static func dequeue() -> [[AnyHashable : Any]] {
    var notifications = [[AnyHashable : Any]]()
    // Retrieve the queued notifications.
    if let userDefaults = UserDefaults(suiteName: applicationGroupName),
      let data = userDefaults.data(forKey: "Notifications"),
      let items = NSKeyedUnarchiver.unarchiveObject(with: data) as? [[AnyHashable : Any]] {
      notifications.append(contentsOf: items)
      // Remove the dequeued notifications from the archive.
      userDefaults.removeObject(forKey: "Notifications")
    }
    return notifications
  }
}

扩展名:

Swift 4.1

  override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
    self.contentHandler = contentHandler
    bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)
    if let bestAttemptContent = bestAttemptContent {
      os_log("New notification received! [%{public}@]", bestAttemptContent.body)
      // Modify the notification content here...
      // Queue the notification and notify the application to process it
      UserDefaultsManager.queue(notification: bestAttemptContent.userInfo)
      notifyApplication()
      contentHandler(bestAttemptContent)
    }
  }

  func notifyApplication() {
    let name: CFNotificationName = CFNotificationName.init("mutableNotificationReceived" as CFString)
    if let center = CFNotificationCenterGetDarwinNotifyCenter() {
      CFNotificationCenterPostNotification(center, name, nil, nil, true)
      os_log("Application notified!")
    }
  }

应用程序:

Swift 4.1

  // Subscribe to the mutableNotificationReceived notifications from the extension.
  if let center = CFNotificationCenterGetDarwinNotifyCenter() {
    let name = "mutableNotificationReceived" as CFString
    let suspensionBehavior = CFNotificationSuspensionBehavior.deliverImmediately
    CFNotificationCenterAddObserver(center, nil, mutableNotificationReceivedCallback, name, nil, suspensionBehavior)
  }

  let mutableNotificationReceivedCallback: CFNotificationCallback = { center, observer, name, object, userInfo in
    let notifications = UserDefaultsManager.dequeue()
    for notification in notifications {
      // Update your Core Data contexts from here...
    }
    print("Processed \(notifications.count) dequeued notifications.")
  }