Обновление # 4
- Я переупорядочил этот пост, чтобы его было легче читать. То, что вы прочтете ниже, подробно расскажет об ошибке, с которой я столкнулся при использовании SwiftUI. Недавно я запросил поддержку на уровне кода у Apple, который подтвердил то же самое и попросил обратиться к отзыву о разрешении (что также было сделано, пока нет ответа).
Ошибка заключается в следующем : После отображения List или ForEach в представлении SwiftUI, если вы изменяете это представление, изменяя количество элементов в списке, пользовательский интерфейс блокируется, пока он пытается вычислить количество строк, которые изменились / должны быть изменены.
Я видел других, кто сталкивался с этой ошибкой на форумах разработчиков Apple. Их временное решение состояло в том, чтобы «установить массив пустым», таким образом полностью очистив список в течение примерно 100 миллисекунд, прежде чем изменять указанный набор данных. Это позволит избежать достаточной блокировки для пользователей, выполняющих итерацию List или ForEach с использованием массива данных.
Проблема в том, что при использовании CoreData, как описано в этом посте, нет никакого способа очистить список между нажимаемыми буквами (запросами на выборку).
В обновлении #3, есть проект GitHub, который показывает образец этой проблемы с примерами данных.
Любой вклад в обходные пути приветствуется.
Обновление # 3
Не очень хорошо. Как описано в этом посте , я смог перейти от использования CoreData к локальной базе данных SQLiteфайл. Мои результаты заключались в том, что поиск был таким же медленным, как при использовании CoreData. Я не знаю, что здесь происходит. Но, может быть, это что-то с отображением результатов на выходе SwiftUI? В любом случае, поиск и отображение большого количества данных кажется невозможным.
Я опубликовал пример проекта, который демонстрирует эту проблему на GitHub, согласно запросу Дж. Доу. Этот проект можно найти здесь
Надеюсь, кто-нибудь увидит, что я делаю не так. Мне трудно поверить, что это всего лишь ограничение iOS ..
Оригинальный пост
Есть идеи?
Я чувствую, что япропустить что-то фундаментальное. Мой запрос на выборку (код ниже) очень медленный. Я попытался добавить индекс к модели CoreData с отрицательным улучшением (предложение Дж. Доу ниже). Я думаю, может быть, мне нужно как-то добавить объявление fetchBatchSize в запрос на выборку (разобрался с этим - см. Обновление № 2 ниже - без помощи), но с помощью обёртки свойства @FetchRequest в SwiftUI, похоже, нет способасделай это.
Приведенный ниже код работает с тестовым набором данных из примерно 5000 записей. При поиске при каждом изменении ввода (с введением каждой буквы) поиск запускается снова, что приводит к остановке системы (более 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 медленно пишут
Обновление № 2:
Мой оригинальный вопрос спрашивал, как добавитьлимит партии на мой выбор, чтобы посмотреть, поможет ли это. Я был в состоянии переписать выборку без использования оболочки FetchRequest, используя NSFetchRequest и добавил ограничение партии. Ничего не помогло.
Еще раз спасибо