2
votes

PROBLEM: Analyzing an iOS app with xcode instruments it appears to be a small but crucial (the snippet is indirectly executed all through the project) memory leak.

DESRCIPTION: We don't make any use of Entities references and follow the typical apple suggested core data object context stack

Here is a screenshot of instruments showing an apparent leak due to NSAsynchronousFetchRequest maintaining a mutual indirect reference to a NSFetchResult

enter image description here

Here is the code snippet triggering the leak (removeing all the non-neccessary code, even the [weak self] still doesn't change it) according to Instruments

let anEntityFetch = NSFetchRequest<NSFetchRequestResult>(entityName: AnEntity.entityName)

let asyncFetchRequest = NSAsynchronousFetchRequest(fetchRequest: rangeQuantityFetch) { (asynchronousFetchResult) -> Void in
    //
}

do {
    // commenting out the execute there is no leak anymore
    _ = try managedObjectContext.execute(asyncFetchRequest)

} catch {
}

The same thing happens enabling compile optimization flags.

QUESTION: Is there a possibility that it is only an Instruments or xcode bug? Or that it is a known core data issue? Or any useful hint to address me to the problem source would be really appreciated.

1

1 Answers

1
votes

It appears to be an issue with the core data object contexts stack. In the configuration we have the a main context having as parent a write context that has the actual persistence coordinator. According to memory-leak-on-nspredicate-that-used-in-fetch-request-to-fetch-nsmanagedobject the problem is with the main context haveing a parent.

To solve this either

  • change the core data stack as pointed in the answer
  • or (seems to work but is not a clean solution) extend the NSAsynchronousFetchRequest to set to nil the request property after the completion block is called (this way the reference cycle is broken and resources can be deallocated by ARC).