Операция Realm без уведомления токенов - PullRequest
1 голос
/ 28 февраля 2020

У меня есть уведомления Realm в фоновом потоке, созданном с помощью следующего кода (взятого с сайта Realm)

class BackgroundWorker: NSObject {

    private let name: String
    private var thread: Thread!
    private var block: (()->Void)!


    init(name: String) {
        self.name = name
    }

    @objc internal func runBlock() {
        block()
    }

    internal func start(_ block: @escaping () -> Void) {
        self.block = block
        if thread == nil {
            createThread()
        }

        perform(
            #selector(runBlock),
            on: thread,
            with: nil,
            waitUntilDone: false,
            modes: [RunLoop.Mode.default.rawValue]
        )
    }


    private func createThread() {
        thread = Thread { [weak self] in
            while (self != nil && !self!.thread.isCancelled) {
                RunLoop.current.run(
                    mode: RunLoop.Mode.default,
                    before: Date.distantFuture)
            }
            Thread.exit()
        }
        thread.name = name
        thread.start()
    }

    func stop() {
        thread.cancel()
    }

}

И использующего фонового работника, как это

struct RealmBackGroundWorker {

  static var tokens: [NotificationToken] = []
  static let backgroundWorker = BackGroundWorker(name: "RealmWorker")

  static func start() {
    backgroundWorker.start {
      self.tokens = ...
    }
  }
}

Фоновые уведомления отлично работает Но мне часто нужно сохранять данные в области без уведомления об этих транзакциях. Из того, что я обнаружил, не похоже, что существует способ записи данных без уведомления всех токенов. Вы всегда должны указывать токены, которые хотите игнорировать. Как я могу записать данные в Царство, не уведомляя эти фоновые токены?

1 Ответ

0 голосов
/ 29 февраля 2020

Позвольте мне предварить этот ответ несколькими вещами. Веб-сайт Realm, с которого ОП получил свой код, был здесь Уведомления Realm в фоновых потоках с помощью Swift , и часть этого кода заключалась в том, чтобы не только запустить runl oop в фоновом потоке для обработки Realm функции, но также для обработки уведомлений в том же потоке.

Этот код довольно старый - 4+ года и несколько устарел. По сути, есть и лучшие варианты. От Apple:

... более новые технологии, такие как Grand Central Dispatch (GCD), предоставляют более современную и эффективную инфраструктуру для реализации параллелизма

Но для решения вопроса, если наблюдатель добавляется в результаты Realm в потоке A, то все уведомления также будут появляться в потоке A. Например, токен, возвращенный функцией наблюдения, привязан к этому потоку.

Похоже, что OP хочет для записи данных без получения уведомлений

Я не хочу синхронизировать c локальные изменения на сервере, поэтому я хотел бы вызвать .write (withouNotifying: RealmWorkBlock.tokens)

и

Мне нужен способ записи данных в базу данных области без уведомления об этих уведомлениях.

Принимая во внимание, что эти уведомления будут появляться в том же потоке, что и Runl oop. Вот код, который нам нужно посмотреть на

  static func start() {
    backgroundWorker.start {
      self.tokens = ...
    }

и, в частности, на эту строку

self.tokens = ...

, потому что ... это важная часть. Это ... приводит к этой строке (из документов)

self?.token = files.observe { changes in

, где добавляется наблюдатель, который генерирует уведомления. Если никаких уведомлений не требуется, то этот код, начиная с self? .Token, может быть полностью удален, так как это единственная цель - генерировать уведомления.

Одна мысль состоит в том, чтобы добавить другой init в фоновый рабочий класс, чтобы иметь фоновый работник без уведомлений:

static func start() {
   backgroundWorker.startWithoutNotifications()
}

Еще одна мысль - воспользоваться более современным подходом и использовать DispatchQueue с пулом автоматического выпуска, который полностью исключает необходимость в этих классах, будет работать в фоновом режиме, освобождая пользовательский интерфейс. объявление не включает токены или уведомления.

DispatchQueue(label: "background").async {
    autoreleasepool {
      let realm = try! Realm()
      let files = realm.objects(File.self).filter("localUrl = ''")
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...