【问题标题】:How to save remote notification data into Core Data(Database) from NotificationServiceExtension如何从 NotificationServiceExtension 将远程通知数据保存到核心数据(数据库)中
【发布时间】:2018-01-03 10:15:42
【问题描述】:

我已经在我的目标应用程序中实现了 NotificationServiceExtension,它运行良好。

  • 创建的 AppgroupID

     lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator? = {
    
         var coordinator: NSPersistentStoreCoordinator? = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel)
         let options = [
             NSMigratePersistentStoresAutomaticallyOption: true,
             NSInferMappingModelAutomaticallyOption: true
             ]
    
         let oldStoreUrl = self.applicationDocumentsDirectory.appendingPathComponent("Model.sqlite")
         let directory: NSURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: AppGroupID)! as NSURL
         let newStoreUrl = directory.appendingPathComponent("Model.sqlite")!
    
         var targetUrl : URL? = nil
         var needMigrate = false
         var needDeleteOld = false
    
    
         if FileManager.default.fileExists(atPath: oldStoreUrl.path){
            needMigrate = true
            targetUrl = oldStoreUrl
         }
         if FileManager.default.fileExists(atPath: newStoreUrl.path){
            needMigrate = false
            targetUrl = newStoreUrl
    
            if FileManager.default.fileExists(atPath: oldStoreUrl.path){
                needDeleteOld = true
            }
         }
         if targetUrl == nil {
            targetUrl = newStoreUrl
         }
    
         if needMigrate {
            do {
                try coordinator?.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: targetUrl!, options: options) 
                if let store = coordinator?.persistentStore(for: targetUrl!) {
                    do {
                        try coordinator?.migratePersistentStore(store, to: newStoreUrl, options: options, withType: NSSQLiteStoreType)
    
                    } catch let error {
                        print("migrate failed with error : \(error)")
                    }
                }
            } catch let error {
                //CrashlyticsHelper.reportCrash(err: error as NSError, strMethodName: "migrateStore")
                print(error)
            }
        }
    
        if needDeleteOld {
            self.deleteDocumentAtUrl(url: oldStoreUrl)
            self.deleteDocumentAtUrl(url: self.applicationDocumentsDirectory.appendingPathComponent("Model.sqlite-shm"))
            self.deleteDocumentAtUrl(url: self.applicationDocumentsDirectory.appendingPathComponent("Model.sqlite-wal"))
        }
    
        do {
            try coordinator!.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: targetUrl, options: options)
        } catch var error as NSError {
            coordinator = nil
            NSLog("Unresolved error \(error), \(error.userInfo)")
            abort()
        } catch {
            fatalError()
        }
        return coordinator
    
    }() 
    
      **EDIT:**
    
    lazy var applicationDocumentsDirectory: URL = {
    
    let urls = Foundation.FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
    return urls[urls.count-1]}()
    
    override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
    
     self.contentHandler = contentHandler
     bestAttemptContent = (request.content.mutableCopy() as? 
     UNMutableNotificationContent)
    
    if let bestAttemptContent = bestAttemptContent {
        // Modify the notification content here...
        print("Mutable Data %@",bestAttemptContent)
        bestAttemptContent.title = "\(bestAttemptContent.title)"
        //bestAttemptContent.title = "Notification"
    
         let apnsDic = bestAttemptContent.userInfo["aps"] as! NSDictionary
            // NotificationManager.sharedInstance.handlePushNotification(byUserTapped: true, content: apnsDic)
            contentHandler(bestAttemptContent)
    
    } }
    
      // Storing APNS dictionary into database from extension
    
      func handlePushNotification(byUserTapped : Bool,content : NSDictionary) {
    
     let moduelDataDic = content.mutableCopy() as! NSMutableDictionary
    
    let entity2 =  NSEntityDescription.entity(forEntityName: "TextMessage",
                                              in: CoreDataStorage.sharedInstance.mainQueueCtxt!)
    
    let textMsg = NSManagedObject(entity: entity2!,
                                  insertInto: CoreDataStorage.sharedInstance.mainQueueCtxt) as? TextMessage
    
    let trimmedMessage = (moduelDataDic.object(forKey: "msgbody")! as AnyObject).trimmingCharacters(in: .whitespacesAndNewlines)
    
    textMsg?.message = trimmedMessage
    msgInfo?.toText = textMsg
    rosterInfo.time = composeMsgDate as Date
    rosterInfo.addToToMessageInfo(NSSet(object: msgInfo!))
    
    DispatchQueue.main.async {
    
        let context = CoreDataStorage.sharedInstance.mainQueueCtxt
        if let moc = context {
            if moc.hasChanges {
                do {
                    try moc.save()
                } catch {
                    let nserror = error as NSError
                    print("Could not save In NotficationManager \(nserror), \(nserror.userInfo)")
                }
            }
        }
    
    } }
    

    在应用程序后台模式下,我正在获取存储在上述 NotificationServiceExtension 方法中的数据,结果我可以从 manageObject 表 (messageInfo) 中获取数据,但没有任何数据进入关系“let setArray = rosterInfo?.toMessageInfo”

    let resultPredicate = NSPredicate(format: "messageID == %@", 
    moduelDataDic.object(forKey: "message_id")! as! CVarArg)
    
    let messageInfoAry = 
    self.fetchMessagesFromCoreDataWithPredicate(resultPredicate: 
    resultPredicate, sortDescriptorKey: "time", isAscending: true, 
    fetchLimit: false, managedContext: self.getManageObjectContext())
    if messageInfoAry.count > 0 {
    
    let rosterInfo = (messageInfoAry[0] as! MessageInfo).toRoster
    let msgInfo = messageInfoAry[0] as! MessageInfo
    
    // Here i don't see msgInfo in this relationship but after relaunching my application i can able to see that same object
    
    let setArray = rosterInfo?.toMessageInfo 
    

    任何人的帮助?

【问题讨论】:

  • 究竟发生了什么“我可以看到数据只有奇怪的行为”?
  • @shallowThought :在我的情况下,我可以在应用程序进入终止模式时保存数据,但是在技术上首先处于后台模式时,我的扩展委托调用了我将远程通知数据存储到核心数据的位置,之后我的应用程序在这里调用的远程通知代表我正在尝试获取我从扩展中存储但看不到的相同数据。重新启动应用程序后,我可以看到相同的数据。
  • 我没看懂,抱歉。
  • 您发布了您的 persistentStoreCoordinator 的代码。请您也发布通知保存的代码吗?
  • 尝试检查模拟器中的核心数据模型位置(您可以查看您对所有内容都具有权限的模拟器)。我认为 Notification 扩展程序的应用程序目录与实际应用程序不同,因为它是作为所有扩展程序的新单独捆绑包。

标签: ios swift core-data notifications serviceextension


【解决方案1】:

尝试将以下代码添加到您的 AppDelegate 类并进行测试。

    func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {

    completionHandler(.newData)
    performSelector(inBackground: #selector(saveNewNotificationInBackground(userInfo:)), with: userInfo)
}

@objc func saveNewNotificationInBackground(userInfo: [AnyHashable: Any]) -> Void {
    //save notification using core data
}

【讨论】:

  • Jayachandra A:当我的应用程序进入后台模式时,反向关系不起作用。 rosterInfo.addToToMessageInfo(NSSet(object: msgInfo!)) 在这里我以一对多的关系形式存储数据!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-19
  • 2015-02-26
  • 1970-01-01
  • 2013-09-24
  • 2010-11-09
  • 1970-01-01
相关资源
最近更新 更多