Комбинат: Как очистить ресурсы во время отмены AnyCancellable? - PullRequest
1 голос
/ 19 апреля 2020

Обзор:

  • У меня есть задача asyn c для извлечения из базы данных
  • Я создал Future для задачи asyn c (выборка из базы данных ).

Вопрос:

  • Как выполнить пользовательский код при отмене Future?

Цель:

  • Я бы хотел, чтобы соединение с базой данных было закрыто при отмене подписки.

Например, я хотел бы использовать Combine для переписывания этого вспомогательного метода:

// Similar to https://developer.apple.com/documentation/coredata/nspersistentcontainer/1640564-performbackgroundtask
func withDatabaseFTSContext(block: @escaping (FMDatabase?) -> Void) {
  queue.async {
    guard let database = self.database else {
      block(nil)
      return
    }

    database.open()
    let simpleTokenizer = FMSimpleTokenizer(locale: nil)
    FMDatabase.registerTokenizer(simpleTokenizer, withKey: "simple")
    database.installTokenizerModule()

    block(database)

    database.close()
  }
}

Могу ли я использовать Combine, чтобы переписать этот метод для возврата FMDatabase в качестве параметра издателя?

Я пытался использовать Combine, но он не работает. База данных будет закрыта до cancel()

private func withDatabaseFTSContext() -> AnyPublisher<FMDatabase?, Never> {
  return Future<FMDatabase?, Never> { promise in
    self.queue.async {
      guard let database = self.database else {
        promise(.success(nil))
        return
      }

      database.open()
      let simpleTokenizer = FMSimpleTokenizer(locale: nil)
      FMDatabase.registerTokenizer(simpleTokenizer, withKey: "simple")
      database.installTokenizerModule()

      promise(.success(database))

      database.close() // When to close this database? Currently it will be closed before `cancel()`
    }
  }.eraseToAnyPublisher()
}

1 Ответ

0 голосов
/ 22 апреля 2020

Краткий ответ: нет обратного вызова, который запускает базовое будущее, которое вы можете использовать для очистки подписчика cancel. В дизайне Combine эти функции преднамеренно разделены и не имеют ссылочных ссылок на своих издателей.

(Кроме того, Future - сложная фигура в мире Combine, поскольку замыкание вызывается сразу после создания время, а не когда у вас есть подписка (если вы хотите, оберните в издателя Future в отложенного издателя)).

Все, что говорится, что вы, вероятно, хотите сделать, чтобы решить вашу основную проблему Переосмыслите, как вы относитесь к этому, чтобы разделить заботы об управлении экземпляром FMDB и публикации данных. Одним из примеров, который был достаточно полезен в этом контексте, является создание объекта, который содержит время жизни ссылки FMDB, и обрабатывает очистку ресурсов на этом deinit(). Затем у вас также может быть функция, которая отправляет издателю все, что вам нужно, из этого же объекта, а затем семантически изменяется отмена запроса, чтобы только отменять получение базы данных, а не отменять и очищать соединение с базой данных.

...