在 performBackgroundTask 闭包中抛出异常

Throwing an exception in performBackgroundTask closure

有一个功能,我正在使用 Cora Data 将网络响应中的数据存储到我的数据库中。如果某些数据丢失、为空或 null 等,该函数应抛出 DataError 异常。 数据库操作必须在 privateQueueContext 的后台任务上 运行。在将数据存储到数据库之前,我检查它是否已经存在(通过 fetchRequest)。如果结果为空,我开始处理数据并将其存储到数据库中。

我可以从闭包外部抛出异常,但我也想在 performBackgroundTask 闭包中抛出异常,但出现构建错误。

方法如下:

private func processLittleItems(informationsFromWebServiceResponse : GetInformationsFromWebServiceResponse) throws {
    guard let littleItemListDataFromResponse = informationsFromWebServiceResponse.littleItemList else {
        throw DataError.dataMissing("littleItemList")
    }
    CoreDataStack.shared.persistentStoreContainer.performBackgroundTask { privateQueueContext in
        for littleItem in littleItemListDataFromResponse {
            let littleItemRequest = LittleItem.fetchRequest() as NSFetchRequest<LittleItem>
            littleItemRequest.predicate = NSPredicate(format: "id = %@", littleItem.iD!)
            littleItemRequest.fetchLimit = 1

            do {
                let littleItemlist = try privateQueueContext.fetch(littleItemRequest)
                if (littleItemlist.isEmpty) {
                    let newLittleItem = LittleItem(context: privateQueueContext)
                    guard let littleItemId = littleItem.iD else {
                        return  // HERE SHOULD BE THROW EXCEPTION, NOT JUST A RETURN
                    }
                    newLittleItem.id = littleItemId

                    newLittleItem.optionalThing = littleItem.optionalThing ?? false
                }
            } catch let error as NSError {
                fatalError("Unresolved error \(error), \(error.userInfo)")
            }
        }
        do {
            try privateQueueContext.save()
        } catch let error as NSError {
            fatalError("Unresolved error \(error), \(error.userInfo)")
        }
    }
}

你能帮忙吗?

提前感谢您提供的任何帮助。

不幸的是,这并不容易。 如果 processLittleItems 的调用者期望函数出现异常(或 return 值),则它必须等到所有内容都已存储。因此,异步处理在这种情况下将不起作用。 所以你必须重新考虑如何在你的应用程序中完成错误处理:

  • 要么processLittleItems的调用者需要等待,因此你必须移除后台作业并同步进行所有操作
  • 或者调用者不能等待(因为这会阻塞 UI 线程)。在这种情况下,调用者可以提供一个完成处理程序,然后您可以从后台闭包中提交 error/success 代码。

Andreas Oetjen 是对的。你抛出的基本上是同步方法的异常,而不是异步方法。

一个选项是根据您的逻辑定义您自己的完成处理程序或回调,并使用它来发回错误并在需要时使用它。 示例:

private func processLittleItems(informationsFromWebServiceResponse : GetInformationsFromWebServiceResponse, completion: (_ error: Error?, object: Any?) -> Void)

以及发生异常时。 completion('your exception', nil)

希望对您有所帮助。