Список сбоев анимации перезагрузки

Сбой анимации

Итак, у меня есть список, который изменяется, когда пользователь вводит ключевое слово для поиска, а когда нет результата, все ячейки разрушаются, и каким-то образом они перелетают в первый раздел, который выглядит некрасиво. Есть ли в моем коде ошибка или это ожидаемое поведение SwiftUI? Спасибо.

import SwiftUI

struct ContentView: View {

    @ObservedObject var viewModel = ViewModel(photoLibraryService: PhotoLibraryService.shared)

    var body: some View {
        NavigationView {
            List {
                Section {
                    TextField("Enter Album Name", text: $viewModel.searchText)
                }
                Section {
                    if viewModel.libraryAlbums.count > 0 {
                        ForEach(viewModel.libraryAlbums) { libraryAlbum -> Text in
                            let title = libraryAlbum.assetCollection.localizedTitle ?? "Album"
                            return Text(title)
                        }
                    }
                }
            }.listStyle(GroupedListStyle())
                .navigationBarTitle(
                    Text("Albums")
                ).navigationBarItems(trailing: Button("Add Album", action: {
                        PhotoLibraryService.shared.createAlbum(withTitle: "New Album \(Int.random(in: 1...100))")
                }))
        }.animation(.default)
    }
}

person Henry Ngan    schedule 05.01.2020    source источник
comment
Вы хотите поместить результат в первый пункт? тогда вам нужно выполнить сортировку вместо фильтрации   -  person Ernist Isabekov    schedule 07.01.2020
comment
@ErnistIsabekov Нет, я хочу отфильтровать результаты. Конечный результат - это не проблема, а переход от полного списка к результату. Вы видите, когда клетки схлопываются, они летят наверх, чтобы выйти из своей секции. Это всего лишь ошибка анимации на долю секунды, но на устройстве она очевидна.   -  person Henry Ngan    schedule 07.01.2020


Ответы (1)


1) вы должны использовать некоторую отладку, чтобы уменьшить потребность в обновлении списка при вводе в поле поиска

2) отключить анимацию строк

Вторая часть - самая сложная. Хитрость заключается в том, чтобы принудительно воссоздать некоторый View, задав его идентификатор.

Вот код простого приложения (чтобы проверить эту идею)

import SwiftUI
import Combine

class Model: ObservableObject {
    @Published var text: String = ""
    @Published var debouncedText: String = ""
    @Published var data = ["art", "audience", "association", "attitude", "ambition", "assistance", "awareness", "apartment", "artisan", "airport", "atmosphere", "actor", "army", "attention", "agreement", "application", "agency", "article", "affair", "apple", "argument", "analysis", "appearance", "assumption", "arrival", "assistant", "addition", "accident", "appointment", "advice", "ability", "alcohol", "anxiety", "ad", "activity"].map(DataRow.init)
    var filtered: [DataRow] {
        data.filter { (row) -> Bool in
            row.txt.lowercased().hasPrefix(debouncedText.lowercased())
        }
    }

    var id: UUID {
        UUID()
    }

    private var store = Set<AnyCancellable>()
    init(delay: Double) {
        $text
            .debounce(for: .seconds(delay), scheduler: RunLoop.main)
            .sink { [weak self] (s) in
            self?.debouncedText = s
        }.store(in: &store)
    }
}

struct DataRow: Identifiable {
    let id = UUID()
    let txt: String
    init(_ txt: String) {
        self.txt = txt
    }
}

struct ContentView: View {

    @ObservedObject var search = Model(delay: 0.5)

    var body: some View {

        NavigationView {
            VStack(alignment: .leading) {

                TextField("filter", text: $search.text)
                    .padding(.vertical)
                    .padding(.horizontal)

                List(search.filtered) { (e) in
                    Text(e.txt)
                }.id(search.id)
            }.navigationBarTitle("Navigation")
        }
    }
}


struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

и я доволен результатом

введите здесь описание изображения

person user3441734    schedule 02.02.2020