title: Multi-threaded core data sometimes returns nil properties
body: <p>I am new to core data. I have an app that uses core data as local store. Writing to and reading from core data is done by background threads. While this works generally, in rare cases are the fetched data wrong, i.e. properties of a fetched entity are <code>nil</code>.<br>
  To check the situation, I wrote a unit test that starts 2 async threads: One fetches continuously from core data, and the other one overwrites continuously these data by first deleting all data, and then storing new data.<br>
  This test pretty quickly provokes the error, but I have no idea why. Of course I guess this is a multi-threading problem, but I don’t see why, because fetches and deletion+writes are done in separate managed contexts of a single <code>persistentContainer</code>.<br>
  I am sorry that the code below is pretty long, although shortened, but I think without it one cannot identify the problem.<br>
  Any help is highly welcome!  </p>
  
  <p>Here is my function to fetch data:  </p>
  
  <pre><code>func fetchShoppingItems(completion: @escaping (Set&lt;ShoppingItem&gt;?, Error?) -&gt; Void) {
      persistentContainer.performBackgroundTask { (managedContext) in 
          let fetchRequest: NSFetchRequest&lt;CDShoppingItem&gt; = CDShoppingItem.fetchRequest()
          do {
              let cdShoppingItems: [CDShoppingItem] = try managedContext.fetch(fetchRequest)
              for nextCdShoppingItem in cdShoppingItems {
                  nextCdShoppingItem.managedObjectContext!.performAndWait {
                      let nextname = nextCdShoppingItem.name! // Here, sometimes name is nil
                  } // performAndWait
              } // for all cdShoppingItems
              completion(nil, nil)
              return
          } catch let error as NSError {
              // error handling
              completion(nil, error)
              return
          } // fetch error
      } // performBackgroundTask
  } // fetchShoppingItems
  </code></pre>
  
  <p>I have commented the line that sometimes crashes the test, since <code>name</code> is <code>nil</code>.  </p>
  
  <p>Here are my functions to store data:  </p>
  
  <pre><code>func overwriteCD(shoppingItems: Set&lt;ShoppingItem&gt;,completion: @escaping () -&gt; Void) {
      persistentContainer.performBackgroundTask { (managedContext) in 
          self.deleteAllCDRecords(managedContext: managedContext, in: "CDShoppingItem")
          let cdShoppingItemEntity = NSEntityDescription.entity(forEntityName: "CDShoppingItem",in: managedContext)!
          for nextShoppingItem in shoppingItems {
              let nextCdShoppingItem = CDShoppingItem(entity: cdShoppingItemEntity,insertInto: managedContext)
              nextCdShoppingItem.name = nextShoppingItem.name
          } // for all shopping items
          self.saveManagedContext(managedContext: managedContext)
          completion()
      } // performBackgroundTask
  } // overwriteCD  
  
  func deleteAllCDRecords(managedContext: NSManagedObjectContext, in entity: String) {
      let deleteFetch = NSFetchRequest&lt;NSFetchRequestResult&gt;(entityName: entity)
      let deleteRequest = NSBatchDeleteRequest(fetchRequest: deleteFetch)
      deleteRequest.resultType = .resultTypeObjectIDs
      do {
          let result = try managedContext.execute(deleteRequest) as? NSBatchDeleteResult
          let objectIDArray = result?.result as? [NSManagedObjectID]
          let changes = [NSDeletedObjectsKey: objectIDArray]
          NSManagedObjectContext.mergeChanges(fromRemoteContextSave: changes as [AnyHashable: Any], into: [managedContext])
      } catch let error as NSError {
          // error handling
      }
  } // deleteAllCDRecords
  
  func saveManagedContext(managedContext: NSManagedObjectContext) {
      if !managedContext.hasChanges { return }
      do {
          try managedContext.save()
      } catch let error as NSError {
          // error handling
      }
  } // saveManagedContext
  </code></pre>