iT邦幫忙

0

Swift Realm 與 Extension 共享資料

小弟在使用RealmSwift搭配Notification Service Extension,碰上了一些問題。
首先,我使用了FCM推播訊息到我的ios設備,我需要儲存我的推播通知到ios設備(使用Realm)
只有兩種情況可以儲存成功
1.app執行中 2.app關閉,點擊橫幅通知
我希望能在app關閉或背景運作中也可以儲存
所以我做了以下這些步驟
1.增加 Notification Service Extension
2.Enable Background fetch/Remote notifications
3.專案與 Notification Service Extension add 到同一個 app groups
並且我更改了Realm的路徑,我在AppDelegates.swift 中增加了以下的code,在NotificationService.swift也加入同樣的code
像這樣

let sharedDirectory: URL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.myapp")! as URL
        let sharedRealmURL = sharedDirectory.appendingPathComponent("db.realm")
        Realm.Configuration.defaultConfiguration = Realm.Configuration(fileURL: sharedRealmURL)

當我在每一個要存取Realm的地方都加上這段,問題就出現了!
app關閉後可以成功儲存訊息,但是不穩定,大約10封通知會成功5封,而且原本app執行中與點擊橫幅通知儲存的功能也失效了。
資料表設定

import Foundation
import RealmSwift

 class Order: Object {

    @objc dynamic var id = UUID().uuidString
    @objc dynamic var name = ""
    @objc dynamic var amount = ""
    @objc dynamic var createDate = Date()

    override static func primaryKey() -> String? {
        return "id"
    }
}
import UIKit
import RealmSwift

class RealmDao: NSObject {

    static let shared = RealmDao()
    private var realm: Realm!

    private override init() {

        self.realm = try! Realm()
    }

    func getRealmObject() -> Realm {
        return self.realm
    }
}

處理推播訊息的 AppDelegate.swift

 let realm =  try! Realm()
    let order: Order = Order()
    var window: UIWindow?
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        ////share Realm
        let sharedDirectory: URL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.myapp")! as URL
        let sharedRealmURL = sharedDirectory.appendingPathComponent("db.realm")
        Realm.Configuration.defaultConfiguration = Realm.Configuration(fileURL: sharedRealmURL)
tainerURL(forSecurityApplicationGroupIdentifier: "group.myapp")

        FirebaseApp.configure()
        if #available(iOS 10.0, *) {
            UNUserNotificationCenter.current().delegate = self
            Messaging.messaging().delegate = self // For iOS 10 data message (sent via FCM)
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound, .badge], completionHandler: { granted, error in
                if granted {
                    print("ok...")
                } else {
                    print("no...")
                }
            })
        } else {
            let settings: UIUserNotificationSettings =
                UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
            application.registerUserNotificationSettings(settings)
        }
        application.registerForRemoteNotifications()
        return true
    }
    func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {  
        let sharedDirectory: URL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.myapp")! as URL
        let sharedRealmURL = sharedDirectory.appendingPathComponent("db.realm")
        Realm.Configuration.defaultConfiguration = Realm.Configuration(fileURL: sharedRealmURL)
        let userInfo = notification.request.content.userInfo 
        print("userInfo: \(userInfo)")
        guard
        let aps = userInfo[AnyHashable("aps")] as? NSDictionary,
        let alert = aps["alert"] as? NSDictionary,
        let body = alert["body"] as? String,
        let title = alert["title"] as? String
        else {
            // handle any error here
            return
        }
        print("Title: \(title) \nBody:\(body)")
        order.name = title
        order.amount = body
        try! realm.write {
            realm.add(order)
        }
        completionHandler([.badge, .sound, .alert])
    }

NotificationService.swift 全部(處理app關閉下的推播通知)

import UserNotifications
import Firebase
import UIKit
import RealmSwift
import Realm

class NotificationService: UNNotificationServiceExtension {

    let realm = try! Realm()
    let order: Order = Order()

    var contentHandler: ((UNNotificationContent) -> Void)?
    var bestAttemptContent: UNMutableNotificationContent?

    override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {


        let sharedDirectory: URL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.myapp")! as URL
        let sharedRealmURL = sharedDirectory.appendingPathComponent("db.realm")
        Realm.Configuration.defaultConfiguration = Realm.Configuration(fileURL: sharedRealmURL)


        self.contentHandler = contentHandler
        bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)

        let message = request.content.userInfo
        print("userInfo: \(message)")
        guard
            let aps = message[AnyHashable("aps")] as? NSDictionary,
            let alert = aps["alert"] as? NSDictionary,
            let title = alert["body"] as? String,
            let body = alert["title"] as? String
            else {
                // handle any error here
                return
        }
        print("Title: \(title) \nBody:\(body)")

        order.name = title
        order.amount = body

        try! realm.write {
            realm.add(order)
        } 
        if let bestAttemptContent = bestAttemptContent {

            // Modify the notification content here...
            bestAttemptContent.body = "\(bestAttemptContent.body) [fortest]"

            contentHandler(bestAttemptContent)
        }
    }

    override func serviceExtensionTimeWillExpire() {
        if let contentHandler = contentHandler, let bestAttemptContent =  bestAttemptContent {
            contentHandler(bestAttemptContent)


        }
    }

}

後來有做一些測試,當我把更改路徑的code刪掉,原本執行中儲存的訊息竟然有被保存下來(不同資料表,一個原始路徑,一個更改過後的路徑)
意思就是,當我更改路徑後,
關閉app的推播訊息有存到新的路徑(當前viewtable顯示新路徑的資料表)
執行中的app推播訊息也有儲存,但是存到舊的路徑(所以在當前的view沒有顯示)
把路徑改回來後(viewtable顯示原本路徑的資料表)剛剛沒有顯示的資料通通都顯示了,所以我誤認他沒有被儲存,小弟不知道為什麼會有這種情況產生,麻煩有經驗的高手告訴小弟該怎麼修改,感激萬分!

尚未有邦友回答

立即登入回答