CoreData 中的异步读取 - 使用 newBackgroundContext + FetchRequest 与 newBackgroundContext + NSAsynchronousFetchRequest 的区别?

2024-04-08

似乎有两种方法可以在 CoreData 中执行异步读取,而不会阻塞主线程 UI。


新的BackgroundContext + NSFetchRequest

来源 :https://www.advancedswift.com/core-data-background-fetch-save-create/ https://www.advancedswift.com/core-data-background-fetch-save-create/

// Create a new background managed object context
let context = persistentContainer.newBackgroundContext()

// If needed, ensure the background context stays
// up to date with changes from the parent
context.automaticallyMergesChangesFromParent = true

// Perform operations on the background context
// asynchronously
context.perform {
    do {
        // Create a fetch request
        let fetchRequest: NSFetchRequest<CustomEntity>

        fetchRequest = CustomEntity.fetchRequest()
        fetchRequest.fetchLimit = 1

        let objects = try context.fetch(fetchRequest)

        // Handle fetched objects
    }
    catch let error {
        // Handle error
    }
}

新的BackgroundContext + NSAsynchronousFetchRequest

Source: https://www.marcosantadev.com/coredata_crud_concurrency_swift_2/ https://www.marcosantadev.com/coredata_crud_concurrency_swift_2/

let privateManagedObjectContext = persistentContainer.newBackgroundContext()

// Creates a fetch request to get all the dogs saved
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "Dog")

// Creates `asynchronousFetchRequest` with the fetch request and the completion closure
let asynchronousFetchRequest = NSAsynchronousFetchRequest(fetchRequest: fetchRequest) { asynchronousFetchResult in

    // Retrieves an array of dogs from the fetch result `finalResult`
    guard let result = asynchronousFetchResult.finalResult as? [Dog] else { return }

    // Dispatches to use the data in the main queue
    DispatchQueue.main.async {
        // Do something
    }
}

do {
    // Executes `asynchronousFetchRequest`
    try privateManagedObjectContext.execute(asynchronousFetchRequest)
} catch let error {
    print("NSAsynchronousFetchRequest error: \(error)")
}

但是,请注意,如果我要启用标志,上面的代码将不幸地导致致命错误-com.apple.CoreData.ConcurrencyDebug 1。到目前为止,我还没有一个好的解决方案。更详细的内容请参考为什么我在这个最简单的 NSAsynchronousFetchRequest 用例中获得 Multithreading_Violation_AllThatIsLeftToUsIsHonor? https://stackoverflow.com/questions/70538970/why-i-am-getting-multithreading-violation-allthatislefttousishonor-for-this-simp


我可以知道,它们之间有什么区别newBackgroundContext + NSFetchRequest vs newBackgroundContext + NSAsynchronousFetchRequest?

我应该如何选择一种而不是另一种?谢谢。


1. 关于__Multithreading_Violation_AllThatIsLeftToUsIsHonor__例外:

这个线程中有详细的讨论:
CoreData 异步获取导致并发调试器错误 https://stackoverflow.com/questions/31728425/coredata-asynchronous-fetch-causes-concurrency-debugger-error

一致认为这是 CoreData 中的一个错误。
有一个错误报告:https://openradar.appspot.com/30692722 https://openradar.appspot.com/30692722截至撰写本文时,该网站已经 8 年后仍然开放。

2.如何正确使用NSAsynchronousFetchRequest

该 API 于 2014 年推出,并在 WWDC 视频中进行了讨论225_sd_whats_new_in_core_data https://devstreaming-cdn.apple.com/videos/wwdc/2014/225xxgzhqylosff/225/225_hd_whats_new_in_core_data.mov?dl=1.
没有提到是否NSAsynchronousFetchRequest应该在主(视图)上下文或后台上下文上使用。

我使用以下命令查看了几个随机实现NSAsynchronousFetchRequest在 GitHub 上,我找到了主要上下文和背景上下文的示例。

一件事你must do然而,当使用后台上下文时,将提取执行包装在perform block (文档 https://developer.apple.com/documentation/coredata/using_core_data_in_the_background).
在您链接的文章和上面摘录的示例中,缺少此内容!
它应该是这样的:

privateManagedObjectContext.perform {
    do {
        try privateManagedObjectContext.execute(asynchronousFetchRequest)
    } catch let error {
        print("error trying to fetch saving objects:", error.localizedDescription)
    }
}

同一篇文章还有另一个潜在问题,因此请持保留态度:

DispatchQueue.main.async {
    // here the objects in result (belongs to private context) are
    // accessed on the main queue – the whole point is to *not* do that!
    // one might get away with it because it is only read access to id
    // but good luck debugging this...
    let dogs: [Dog] = result.lazy
        .flatMap { $0.objectID }
        .flatMap { mainManagedObjectContext.object(with: $0) as? Dog }
    // ...

我理解的方式NSAsynchronousFetchRequest是它最好在主上下文中使用,其目的实际上是向您隐藏后台上下文业务。

So: mainContext + NSAsynchronousFetchRequest

3. 我应该如何选择?

在我看来,这NSAsynchronousFetchRequest创建的初衷是为了简化我们的异步核心数据获取。为此,您很可能会利用它来发挥自己的优势,特别是当您需要处理进度和取消时。

但是我可能不会在我的项目中使用它,因为

  • 文档很少
  • 它维护得不好(永远存在错误)
  • 它没有很好地适应(例如流行且优秀的 Core Data 包装器核心商店 https://github.com/JohnEstropia/CoreStore不使用它)

最后一个想法 - 在进行异步获取之前,请确保您确实需要它。首先优化查询、数据模型或批处理设置的性能可能会更好。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

CoreData 中的异步读取 - 使用 newBackgroundContext + FetchRequest 与 newBackgroundContext + NSAsynchronousFetchRequest 的区别? 的相关文章

  • 统一的阿拉伯语输入字段

    有没有办法将输入字段的语言统一更改为阿拉伯语 我尝试了ArabicSupport 它正确显示了阿拉伯语 但将其与输入字段一起使用却不起作用 因为 GameObject Find input field GetComponent
  • 动态更新 UIAlertView 消息和换行符问题

    我需要在 UIAlertView 的消息中显示多行文本 我尝试过添加 n 但没有效果 它仍然显示 这是一个示例 但是 如果我将 iPhone 切换为横向模式 它会按照我的预期显示该消息 然后 如果我切换回纵向模式 它也会正确显示 更新 经过
  • Swiftui 应用程序在 iOS 14 / 15 上使用不同的 SearchBar (ViewModifier) 时崩溃

    我在 iOS 14 上使用 SwiftlySearch 在 iOS 15 上使用 searchable struct CompatibleSearchBarModifier ViewModifier Binding var text Str
  • Swift 客户端和根 SSL 证书身份验证

    积分得到token api of QLIK server with ssl证书 但执行任务后我收到这样的错误 完成时出现错误 代码 999 Your hostname and endpoint let hostname YOUR HOST
  • 苹果的外部配件(蓝牙)仅适用于 MFI 设备? [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我的学士论文的目标是通过蓝牙适配器将光串行设备连接到 iPad 目前我正在努力应对苹果的限制 我经常在网上看到我可以使用支持的配置文件 h
  • 自定义 UIPopoverController 视图背景和边框颜色

    是否可以更改弹出视图的边框颜色 导航栏样式 颜色和箭头样式 颜色 如果是这样 怎么办 如果有一些示例代码可用 那就太好了 iOS 7以上 可以更改backgroundColor of UIPopoverController这会影响导航背景颜
  • 如何在iOS8自定义键盘上方添加工具栏?

    My problem is write picture I really need you help Maybe inputAccessoryView inputAccessoryViwController can be used but
  • 重新定位时 Mapbox 默认的 compassView 会给出奇怪的结果

    我遇到一种情况 必须将地图框罗盘视图重新定位到不同的位置 当我以其他点作为其 compassView 轴旋转地图时 compassView 现在正在旋转 并给了我一个奇怪的结果 附截图 黑色mapBox默认罗盘图标是旋转的 参考截图 这是
  • Swift 3 GCD API 更改后的dispatch_once

    新语法是什么dispatch once在语言版本 3 中进行更改后的 Swift 中 旧版本如下 var token dispatch once t 0 func test dispatch once token These 对 libdi
  • 我可以在滚动时固定表格的 tableHeaderView 位置吗?

    我有一个表视图 并在其 tableHeaderView 上附加了一个 UISegmentedControl 如何使 tableHeaderView 固定 以便即使在滚动表视图时也始终可以在同一位置查看 UISegmentedControl
  • 如何使用 SwiftUI 拖动工作滑块

    我想拖动一个滑块 当然也让它滑动 我可以做其中之一 但我不能两者都做 如何拖动并拥有可用的滑块 我也尝试找到一种方法来删除手势 但我找不到方法来做到这一点 还尝试了 Apple Composition SwiftUI Gestures 文档
  • TypeError:cli.init 不是 React Native 的函数

    在 MacBook Air M1 芯片中运行 npx react native init appName 时 TypeError cli init is not a function at run opt homebrew lib node
  • 运行时警告 CLSUserDefaults 实施了两次

    在 cocoapod 源中使用 import 语法时 我在 pod 定义的类中看到了与下面类似的警告 但这是一个内部苹果类定义 CLSUserDefaults 我无法控制它 也不会进行子类化 我不知道这是否真的造成了问题 但它不应该发生 o
  • iOS 9.3 出现新的 UIPDFPageRenderOperation 错误?

    我正在向 UIWebView 添加一些 PDF 链接 每次加载并做出滚动手势时 都会收到此错误 objc 910 UIPDFPageRenderOperation 对象 0x14acaca10 过度释放 当已经解除分配时 打断 objc o
  • iOS 上邮件到达时收到通知吗?

    当邮件到达标准邮件应用程序时 有没有办法让应用程序收到通知 更准确地说 我想编写一个应用程序 它能够从标准邮件应用程序读取传入的电子邮件 其中包含自定义 txt 格式的新联系人或事件 然后 应用程序应将此新联系人 事件添加到 ipad 反之
  • 如何为 App Store 添加关联域? - App Store Connect 的 app-ads.txt 文件

    如您所知 Admob 向发布商发送了有关 app ads txt 文件的电子邮件 Admob 在电子邮件中表示 因此 我们邀请您仔细检查您的 app ads txt 文件 如果 您已经在发布日期之前发布了一份 文件 应发布在列出的网站的根目
  • Quickblox 聊天未进行身份验证

    我在我的应用程序中使用 Quickblox 进行一对一聊天 用户已经登录 但是当我尝试登录聊天时 出现以下错误 2014 03 31 12 42 09 532 MyChat 2175 3803 QBChat didNotAuthentica
  • geocoder.geocodeAddressString 今天不再适用于快速更新

    https developer apple com library prerelease mac releasenotes General APIDiffsMacOSX10 11 Swift CoreLocation html https
  • Base64Transcoder.m 重复符号

    我想使用 SKPSMTPMessage 库 唯一的问题是这个库包含文件 Base64Transcoder m 由于我有 Dropbox SDK 该文件会出现重复错误 我该如何解决这个错误 我不能直接删除 Base64Transcoder m
  • iOS swift 应用程序启动时出现黑屏

    我有个问题 当我启动我的应用程序时 会看到黑屏几秒钟 然后出现启动屏幕 我的启动画面不是默认的 我使用了视图控制器 因为我的启动画面有一个动画 我搜索了一个解决方案 我得到了这个 在我的闪屏加载 iPhone 之前出现黑屏 https st

随机推荐