CoreDataStack loadPersistentStores no completionHandler callback

In the past few weeks, about Coredata, I added the database backup function. After going online, I received feedback from users that the app opened with a white screen and could not be started normally.

By investigating the reason why the App cannot be started, it is that there is no callback after loadPersistentStores is executed.

This problem has never been reported by users before, until I added the code for data backup, so I suspect it has something to do with data backup.

Below is the code for data backup

func backupPersistentStore(atIndex index: Int, fileName: String) throws -> TemporaryFile {
        precondition(persistentStores.indices.contains(index), "Index \(index) doesn't exist in persistentStores array")
        let sourceStore = persistentStores[index]
        let backupCoordinator = NSPersistentStoreCoordinator(managedObjectModel: managedObjectModel)

        let intermediateStoreOptions = (sourceStore.options ?? [:])
            .merging([NSReadOnlyPersistentStoreOption: true],
                     uniquingKeysWith: { $1 })
        let intermediateStore = try backupCoordinator.addPersistentStore(
            ofType: sourceStore.type,
            configurationName: sourceStore.configurationName,
            at: sourceStore.url,
            options: intermediateStoreOptions
        )

        let backupStoreOptions: [AnyHashable: Any] = [
            NSReadOnlyPersistentStoreOption: true,
            NSSQLitePragmasOption: ["journal_mode": "DELETE"],
            // Minimize file size
            NSSQLiteManualVacuumOption: true,
            ]

        let backupFilename = fileName + ".sqlite"
        let backupFile = try TemporaryFile(creatingTempDirectoryForFilename: backupFilename)
        try backupCoordinator.migratePersistentStore(intermediateStore, to: backupFile.fileURL, options: backupStoreOptions, withType: NSSQLiteStoreType)
        return backupFile
}

When to back up

  1. sceneDidEnterBackground use Operation with UIApplication.shared.beginBackgroundTask
class BackUpOpeartion: Operation {
   
  override func main() {
    LocalBackupManager.shared.backupSync()
  }
   
  static func canHandler() -> Bool {
    let backupStrategy = LocalUserDefaults.standard.backupUiModel
    let lastBackUpDate = LocalUserDefaults.standard.lastBackUpDate
     
    let now = Date()
    let sixHour: TimeInterval
     
    #if DEBUG
    sixHour = TimeInterval(0.15 * 60 * 60)
    #else
    sixHour = TimeInterval(backupStrategy.backupFrequency) // 6h
    #endif
     
    let backupDate = lastBackUpDate + sixHour
     
    // Clean the database at most once per week.
    guard now > backupDate else {
      "It's not time to backup".debugLog()
      return false
    }
     
    return true
  }
   
  static func doWhenEnterBackground() {
    if !canHandler() {
      return
    }
     
    var bgtToken = UIBackgroundTaskIdentifier.invalid
    bgtToken = UIApplication.shared.beginBackgroundTask(expirationHandler: {
      UIApplication.shared.endBackgroundTask(bgtToken)
    })
     
    guard bgtToken != .invalid else{
      return
    }
     
    DispatchQueue.global(qos: .utility).async {
      LocalBackupManager.shared.backupSync { succeed in
        DispatchQueue.main.async {
          if succeed {
            LocalUserDefaults.standard.lastBackUpDate = Date()
          }
          UIApplication.shared.endBackgroundTask(bgtToken)
        }
      }
    }

  }
   
}
  1. BGProcessingTask in AppDelegate
func registerBackgroundTasks() {
    BGTaskScheduler.shared.register(forTaskWithIdentifier: dbBackupId, using: nil) { task in
      self.backupDb(task: task as! BGProcessingTask)
    }
  }

func scheduleDbBackup() {
    if !BackUpOpeartion.canHandler() {
      return
    }
     
    let request = BGProcessingTaskRequest(identifier: dbBackupId)
    request.requiresNetworkConnectivity = false
    request.requiresExternalPower = false
     
    do {
      try BGTaskScheduler.shared.submit(request)
      "submit DbBackup".debugLog()
    } catch {
      print("Could not schedule app refresh: \(error)")
    }
  }

func backupDb(task: BGProcessingTask) {
     
    let queue = OperationQueue()
    queue.maxConcurrentOperationCount = 1
     
    let operation = BackUpOpeartion()
     
    task.expirationHandler = {
      queue.cancelAllOperations()
    }
     
    operation.completionBlock = {
      let success = !operation.isCancelled
      if success {
        LocalUserDefaults.standard.lastBackUpDate = Date()
      }
      task.setTaskCompleted(success: success)
    }
  }

Since before the online backup, there is no feedback about the white screen of the app failing to start, so I feel it is related to the backup

I don't know under what circumstances it would cause CoreDataStack loadPersistentStores no completionHandler callback

can someone help me? Thanks!

CoreDataStack loadPersistentStores no completionHandler callback
 
 
Q