即使在ARC下,在GCD中使用Realm时我们是否必须使用显式自动释放池

在Realm的文档中说:

使用Grand Central Dispatch访问Realm时,您可能也会看到此问题。 当一个领域最终出现在一个调度队列的自动释放池中时会发生这种情况,因为这些池在执行代码后可能不会耗尽一段时间。 在取消分配RLMRealm对象之前,不能重用Realm文件中的数据的中间版本。 要避免此问题,从分派队列访问Realm时应使用显式自动释放池。

这是否意味着即使在ARC下,我们每次都必须在GCD中使用显式自动释放池? 有人可以发布代码示例吗? 这有点重要,但官方文档并没有那么强调

您不必每次都使用显式自动释放池。 对于执行大量并发事务的情况更为相关,并且可能很容易遇到跟踪许多即时版本的风险。 或者,当您想确保通过释放所有打开的访问者来关闭应用程序生命周期中的Realm文件时。

在这一点上,文档更多地被理解为了解技术限制并暗示如何解决这个问题,一旦遇到类似问题而不是一般的最佳实践。 当然,你总能做到这一点并不一定会伤到你(如果你有一把锤子,一切看起来像钉子。),但你不一定要这样做。

并不是每个人都需要额外的复杂function。 了解显式自动释放池需要更深入地了解ARC,这不是一般要求。 如果您有想法,如何以更好的方式解决这些问题,那么您的反馈非常受欢迎。

“ 使用跨线程领域”一节为此提供了示例,在后台队列中插入了一百万个对象:

dispatch_async(queue) { autoreleasepool { // Get realm and table instances for this thread let realm = try! Realm() // Break up the writing blocks into smaller portions // by starting a new transaction for idx1 in 0..<1000 { realm.beginWrite() // Add row via dictionary. Property order is ignored. for idx2 in 0..<1000 { realm.create(Person.self, value: [ "name": "\(idx1)", "birthdate": NSDate(timeIntervalSince1970: NSTimeInterval(idx2)) ]) } // Commit the write transaction // to make this data available to other threads try! realm.commitWrite() } } } 

在一个单独的自动释放池中创建对象创建通常是有意义的,因为当对象释放发生时你无法用ARC真正预测,所以你有一个明确的时间点,当它们最新发生时,这使得你的程序更确定地为你和其他人理解

要避免此问题,从分派队列访问Realm时应使用显式自动释放池。

这是否意味着即使在ARC下,我们每次都必须在GCD中使用显式自动释放池?

我不同意当前接受的答案,在任何后台线程(特别是线程池,如GCD)上,您应该在不再需要时尽快强制关闭Realm实例,以避免版本保留。 在iOS中,使用autoreleasepool { ... }可以强制关闭Realm实例。

因此,对于后台线程,通常建议始终使用显式自动释放池。

 dispatch_async(queue) { autoreleasepool { let realm = try! Realm() //... } } 

最好尽量减少从后台线程提交的事务数,因此您应该尝试使用1个事务而不是N.

 // Break up the writing blocks into smaller portions // by starting a new transaction realm.beginWrite() for idx1 in 0..<1000 { // Add row via dictionary. Property order is ignored. for idx2 in 0..<1000 { realm.create(Person.self, value: [ "name": "\(idx1)", "birthdate": NSDate(timeIntervalSince1970: NSTimeInterval(idx2)) ]) } } // Commit the write transaction // to make this data available to other threads try! realm.commitWrite()