Do we have to use explicit autorelease pool when u

2020-02-12 18:15发布

It is said in Realm's doc:

You may also see this problem when accessing Realm using Grand Central Dispatch. This can happen when a Realm ends up in a dispatch queue’s autorelease pool as those pools may not be drained for some time after executing your code. The intermediate versions of data in the Realm file cannot be reused until the RLMRealm object is deallocated. To avoid this issue, you should use an explicit autorelease pool when accessing a Realm from a dispatch queue.

Does this mean that we must use explicit autorelease pool everytime in GCD even under ARC? Can someone post a code sample? This is kind of important, but the official documentation does not emphasize it so much

标签: ios realm
2条回答
Root(大扎)
2楼-- · 2020-02-12 18:57

To avoid this issue, you should use an explicit autorelease pool when accessing a Realm from a dispatch queue.

Does this mean that we must use explicit autorelease pool everytime in GCD even under ARC?

I disagree with the current accepted answer, on any background thread (especially threadpools such as the GCD), you should always force the close of the Realm instance as soon as possible when it is no longer needed, to avoid version retention. In iOS, forcing the close of a Realm instance is possible with autoreleasepool { ... }.

So for background threads, it is generally recommended to always use an explicit autorelease pool.

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

It's also preferable to minimize the number of transactions you commit from background threads, so you should instead try to have 1 transactions instead of 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()
查看更多
Bombasti
3楼-- · 2020-02-12 19:08

You don't really have to use an explicit autorelease pool every time. It is more relevant for scenarios where you do a lot of concurrent transactions and could easily run into the risk of tracking to many immediate versions. Or when you want to make sure that you close the Realm file in the lifetime of your app by releasing all open accessors to it.

The docs are at this point more to understand as a making aware of technical limitations and a hint how to resolve that once you hit an issue like that than a general best practice. Sure, you could always do that and it wouldn't necessarily hurt you (à la "If you have a hammer, everything looks like a nail."), but you wouldn't necessarily have to do it.

The extra complication of what this exactly means is not required for everyone. Understanding explicit autorelease pools needs a deeper understanding of ARC that is not a general requirement. If you have ideas, how that could be resolved in a better way, your feedback is more than welcome.

The section Using a Realm Across Threads gives an example for that, inserting a million objects in a background queue:

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()
    }
  }
}

It generally makes sense to have object creations in a number like that in a separate autoreleasepool as you can't really predict with ARC when the object releases will happen and so you have an explicit point in time, when they will happen latest, which makes your program more deterministically to understand for you and other humans.

查看更多
登录 后发表回答