gpt4 book ai didi

xcode - SwiftUI 错误 - 列表更改锁定 UI -(旧标题 : SwiftUI CoreData fetch is very slow)

转载 作者:行者123 更新时间:2023-12-03 16:50:35 25 4
gpt4 key购买 nike

更新 #4

  • 我重新排序了这篇文章,以便更轻松地阅读。您将在下面阅读的内容将详细介绍我在使用 SwiftUI 时遇到的错误。我最近请求 Apple 提供代码级别的支持,他确认了这一点,并要求我联系解决问题的反馈(也已完成,但尚未答复)。

  • 错误是这个 :在 SwiftUI View 中显示 List 或 ForEach 后,如果您通过更改列出的项目数来更改该 View ,则 UI 会在尝试计算已更改/需要更改的行数时锁定。

    我在 Apple 开发论坛中看到其他人遇到过这个错误。他们的临时解决方案是“将数组设置为空白”,从而在修改列出的数据集之前彻底清除列表大约 100 毫秒。这将充分避免用户使用数据数组迭代 List 或 ForEach 时的锁定。

    问题是,对于 CoreData,按照本文中的描述使用,似乎没有任何方法可以清除推送的字母之间的列表(获取请求)。

    在更新 #3 中,有一个 GitHub 项目显示了此问题的示例数据。

    对解决方法的任何输入表示赞赏。

    更新 #3

    不好..如 this post中所述,我能够从使用 CoreData 更改为本地 SQLite 数据库文件。我的结果是搜索和使用 CoreData 一样慢。我不知道这里发生了什么。但也许它与 SwiftUI 输出的渲染结果有关?无论哪种方式,搜索和显示大量数据似乎都是不可能的。

    根据 J. Doe 的要求,我在 GitHub 上发布了一个示例项目,该项目演示了这个问题。这个项目可以在 here找到

    我希望有人能看到我做错了什么。我很难相信这只是 iOS 的一个限制。

    原帖

    有任何想法吗?

    我觉得我缺少一些基本的东西。我的获取请求(下面的代码)非常慢。我试图向 CoreData 模型添加一个索引,但有负面改进(来自下面的 J. Doe 的建议)。我想也许我需要以某种方式向 fetch 请求添加一个 fetchBatchSize 声明(想通了这一点 - 请参阅下面的更新 #2 - 没有帮助),但是使用 SwiftUI 中的属性包装器 @FetchRequest,似乎没有办法做这个。

    下面的代码正在处理大约 5,000 条记录的测试数据集。在搜索中,每次更改输入(输入每个字母)时,搜索都会再次运行,这会拖累系统停止(CPU 100+% 和内存使用量增加)。

    在以前的应用程序中,我完成了类似的任务,但这些应用程序使用 SQLite 数据文件并用 ObjC 编写。在这些情况下,事情真的很快,超过了这个测试数据集的 3 倍。

    如果有人能指出我正确的方向来加速我的 CoreData 获取,我将不胜感激。如果我不需要,我不想回到 SQLite 文件。

    非常感谢!

    使用 SwiftUI,这是我的代码:
    struct SearchView: View {


    @Binding var searchTerm:String
    var titleBar:String

    var fetch: FetchRequest<MyData>
    var records: FetchedResults<MyData>{fetch.wrappedValue}

    init(searchTerm:Binding<String>, titleBar:String) {
    self._searchTerm = searchTerm
    self.titleBar = titleBar
    self.fetch = FetchRequest(entity: MyData.entity(), sortDescriptors: [NSSortDescriptor(keyPath: \ MyData.header, ascending: true)], predicate: NSCompoundPredicate(type: .and, subpredicates: [ NSCompoundPredicate(type: .or, subpredicates: [NSPredicate(format: "%K CONTAINS[cd] %@", #keyPath(MyData.title),searchTerm.wrappedValue), NSPredicate(format: "%K CONTAINS[cd] %@", #keyPath(MyData.details),searchTerm.wrappedValue)]), NSPredicate(format: "%K == %@", #keyPath(MyData.titleBar),titleBar)])) //fetch request contains logic for module and search data - need to fix sort order later
    }

    var body: some View {


    List{

    Section(header: SearchBar(text: $searchTerm)) {

    ForEach(records, id: \.self) { fetchedData in

    VStack {
    NavigationLink(destination: DetailView(titleBar: fetchedData.title!, statuteData: fetchedData.details!, isFavorite: fetchedData.isFavorite)) {

    HStack {
    Text(fetchedData.header!)
    .font(.subheadline)

    VStack(alignment: .leading) {
    Text(fetchedData.title!)
    }
    .scaledToFit()

    Spacer()

    if fetchedData.isFavorite {
    Image(systemName: "star.fill")
    .imageScale(.small)
    .foregroundColor(.yellow)
    }
    }
    }
    }
    }
    }.navigationBarTitle(Text("Search"))
    }
    }
    }


    谢谢您的帮助。

    更新:

    在编辑之前,我报告了存储数据的另一个问题,但是,该问题已通过以下帖子解决:

    CoreData writing objects slow

    更新 #2:

    我最初的问题是问如何在我的 fetch 中添加批量限制以查看是否有帮助。我能够在不使用 FetchRequest 包装器的情况下重写获取,使用 NSFetchRequest 并添加了批处理限制。它对这种情况没有任何帮助..

    再次感谢

    最佳答案

    我在 list 中遇到了同样的滚动速度很慢的问题从核心数据中获取结果。与我之前使用 UIKit 的解决方案相比,使用 swiftUI 的速度很慢(相同的数据,相同的获取)。除了必须使用 fetchOffset 和 fetchLimit 我发现一个主要的性能问题是由于使用 NavigationLink .没有 NavigationLink 时性能很好,但使用 NavigationLink 时则不然。
    正在寻找我找到的解决方案 this blog post由 Anupam Chugh 撰写,他写了这篇文章,并提供了我在下面复制的解决方案。我很感激他。这是他的解决方案,不是我的。
    关键是当NavigationLinklist 内使用,目标 View 会立即加载,即使用户尚未导航到该 View 。为了克服这一点,必须使目标 View 变得懒惰。
    就我而言,我在主 View 中选择了一种食物,然后在详细 View 中显示了所选食物的 180 多个属性列表...
    解决方案:
    使用以下代码创建一个新文件

    import SwiftUI

    /// Creates a lazy view from view.
    ///
    /// Helpfull for use of `NavigationLink` within `list`, where destination views are loaded immediately even when the user hasn’t navigated to that view.
    /// Embedding the destination view in LazyView makes the destination view lazy and speeds up performance significantly for long lists.
    ///
    /// ```Swift
    /// NavigationLink(destination: LazyView(Text("Detail Screen"))){
    /// Text("Tap me to see detail screen!")
    /// }
    /// ```
    ///
    /// Source: [Blog post by Anupam Chugh on Medium]( https://medium.com/better-programming/swiftui-navigation-links-and-the-common-pitfalls-faced-505cbfd8029b). Thank you!!!!
    struct LazyView<Content: View>: View {
    let build: () -> Content
    init(_ build: @autoclosure @escaping () -> Content) {
    self.build = build
    }
    var body: Content {
    build()
    }
    }
    并像这样使用它:
    NavigationLink(destination: LazyView(Text("Detail Screen"))){
    Text("Tap me to see detail screen!")
    }
    我希望这对其他人也有帮助。

    关于xcode - SwiftUI 错误 - 列表更改锁定 UI -(旧标题 : SwiftUI CoreData fetch is very slow),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58383419/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com