不通知令牌的领域交易

时间:2020-02-28 18:27:48

标签: swift realm

我在使用以下代码(从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 = ...
    }
  }
}

后台通知效果很好。但是我经常需要将数据保存到领域而无需通知这些事务。从我发现的情况来看,似乎没有一种方法可以在不通知所有令牌的情况下写入数据。您始终必须指定要忽略的令牌。 如何在不通知这些背景标记的情况下将数据写入Realm?

1 个答案:

答案 0 :(得分:-1)

让我以几句话开头这个答案。 OP从其{@ 3}}处获得其代码的Realm网站,该代码的部分要点不仅是在后台线程上启动运行循环以处理Realm函数,而且还要在同一线程上处理通知。

该代码非常古老-已有4年以上的历史,并且有些过时。本质上,可能有更好的选择。来自苹果公司:

...诸如Grand Central Dispatch(GCD)等较新的技术提供了 实施并发的更现代,更高效的基础架构

但是为了解决这个问题,如果将观察者添加到线程A的Realm结果中,那么所有通知也将在线程A上发生。从watch函数返回的令牌已绑定到该线程。

OP似乎想在不接收通知的情况下写入数据

我不想将本地更改同步到服务器,所以我想 致电.write(withouNotifying:RealmWorkBlock.tokens)

我想要一种无需通知即可将数据写入领域数据库的方法 这些通知。

请注意,这些通知将在与运行循环相同的线程上发生。这是我们需要查看的代码

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

尤其是这一行

self.tokens = ...

因为...是重要的部分。那...导致这一行(来自文档)

self?.token = files.observe { changes in

是添加观察者以生成通知的位置。如果不需要通知,则可以完全删除以self?.token开头的代码,因为这是唯一的目的-生成通知。

一个想法是向后台工作人员类添加一个不同的init,以使后台工作人员没有任何通知:

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

另一种想法是采用一种更现代的方法,并将DispatchQueue与自动释放池一起使用,从而完全消除了对这些类的需求,将在后台运行以释放不涉及令牌或通知的UI广告。

DispatchQueue(label: "background").async {
    autoreleasepool {
      let realm = try! Realm()
      let files = realm.objects(File.self).filter("localUrl = ''")
    }
}