【发布时间】:2020-02-11 11:17:25
【问题描述】:
更新 #4
- 我对这篇文章进行了重新排序,以便更轻松地阅读。您将在下面阅读的内容将详细介绍我在使用 SwiftUI 时遇到的错误。我最近要求苹果提供代码级支持,苹果也确认了这一点,并要求我联系反馈以寻求解决方案(这也完成了,还没有答案)。
错误是这样的:在 SwiftUI 视图中显示 List 或 ForEach 后,如果您通过更改列出的项目数来更改该视图,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"))
}
}
}
感谢您的帮助。
更新:
在编辑之前,我报告了存储数据的另一个问题,但是,该问题已通过以下帖子解决:
更新 #2:
我最初的问题是如何在我的 fetch 中添加批次限制以查看是否有帮助。我能够在不使用 FetchRequest 包装器的情况下重写提取,使用 NSFetchRequest 并添加批处理限制。它对这种情况没有任何帮助..
再次感谢
【问题讨论】:
-
您添加了索引?有什么复制项目吗?
-
找到 - 添加索引选项 - 将尝试并报告我的发现..
-
为我的谓词中的两个属性添加了索引,分别和一起。除非我在那里做错了什么,否则没有帮助..
-
复制粘贴代码不起作用。我可以看看,但前提是问题很容易重现。一种方法是使用最少的代码创建一个项目来重现问题并将其上传到 github 并在此处添加 github 链接
-
我会尝试在 AND 复合谓词中交换两个子谓词:首先(快速)和 CONTAINS 进行严格的 == 比较,因为它要慢得多(特别是因为有两个其中的子谓词)。
标签: xcode sqlite core-data swiftui