Как поделиться Realm (используя swift) в расширениях и AppDelegates - PullRequest
0 голосов
/ 16 июня 2019

У меня проблемы с RealmSwift с Notification Service Extension. Я надеюсь, что каждый может помочь мне или дать мне совет. Я искренне благодарю вас всех! И мой английский не очень хороший, дайте мне знать, если что-то неясно.

Сначала я использовал FCM для отправки сообщения на мое устройство ios, мне нужно сохранить свое push-уведомление на устройстве ios (используя Realm). Есть только два случая, которые могут успешно сохранить.

1.app работает

2.app убит / фон, и нажмите, чтобы отправить уведомления баннера. Я надеюсь, что я могу отключить приложение / фон и сохранить его, не нажимая на уведомление баннера.

Итак, я использовал следующий метод

1.Добавить Notification Service Extension в проект

2. Включение фоновой выборки / Удаленные уведомления

3.Проект и Notification Service Extension добавлены в группы приложений Я знаю, что расширение не может обмениваться данными, поэтому я изменил путь по умолчанию Realm.

Я добавил следующий код в AppDelegates.swift и добавил тот же код в NotificationService.swift. как это

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

После того, как я добавил эти коды, когда приложение убито или фон, push-сообщение может быть успешно сохранено в Realm, но не каждый раз, 10 push-уведомлений сохранят только 5, и самое главное, функциональность, которая могла бы иметь были сохранены в приложении, запущенном или щелкнувшем по баннеру уведомление не удалось. (Но он сохраняется, потому что если я отменю код, который изменяет путь к Realm по умолчанию, данные, которые не были сохранены, будут отображены снова)

My Realm class

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

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)


        }
    }

}

Я думаю, что моя проблема, по-видимому, связана с изменением пути по умолчанию, потому что когда я меняю путь, push-уведомление при выполнении сохраняется, но отображается код, который должен удалить путь изменения! Это то, что я пропустил, что заставляет исходный путь все еще существовать (таким образом, push-уведомление в запущенном приложении будет сохранено в другой таблице данных?)

...