我在使用以下代码(从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?
答案 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 = ''")
}
}