Как сделать так, чтобы «Published<[String]>.Publisher» соответствовало «RandomAccessCollection»

Я пытаюсь создать представление, которое обновляется в зависимости от того, переключает ли пользователь кнопку избранного или нет. Я хочу, чтобы все представление реконструировалось, чтобы отображать массив значений всякий раз, когда этот массив значений изменяется. Внутри представления цикл for each должен отображать каждое значение в массиве.

Представление, которое я хочу обновлять каждый раз, когда изменяется saveArray, — это FavView. Но когда я пытаюсь использовать цикл foreach для отображения каждого значения, это saveArray (которое я создал как @Published, чтобы представление реконструировалось), это дает мне ошибку. Общая структура «ForEach» требует, чтобы «Published <[String]>. Издатель» соответствует «RandomAccessCollection». Я сбит с толку, потому что думал, что массивы String можно использовать для каждого цикла. Разве это не правда? Как пройтись по массиву @Published? Спасибо! Это мой код для сохраненного массива (в ViewModel) и FavView, в котором я хочу отобразить его, для каждого.

struct ContentView: View {
    @StateObject private var statNavManager = StatsNavigationManager()

    @State private var saved: [String] = []

    var body: some View {
        TabView {
                    
            StatsView(saved: $saved)
            .tabItem {
                Label("Home", systemImage: "house")
            }

            FavView(saved: $saved)
                .tabItem {
                    Label("Saved", systemImage: "bookmark")
            }
        }
        .environmentObject(statNavManager)
    }
}

final class ViewModel: ObservableObject {
        @Published var items = [Item]()
        @Published var showingFavs = true
        @Published var savedItems: Set<String> = []
        @Published var savedArray: [String]
        // Filter saved items
    
        var filteredItems: [String]  {
            //return self.items
            return savedArray
        }

        var db = Database()
        
        init() {
            self.savedItems = db.load()
            self.items = db.returnList()//the items
            self.savedArray = Array(db.load())
            print("savedarray", savedArray)
            print("important!", self.savedItems, self.items)
        }
        
        func contains(_ item: Item) -> Bool {
                savedItems.contains(item.id)
            }
        
        // Toggle saved items
        func toggleFav(item: Item) {
            print("Toggled!", item)
            if contains(item) {
                savedItems.remove(item.id)
                if let index = savedArray.firstIndex(of: item.id) {
                    savedArray.remove(at: index)
                }
            } else {
                savedItems.insert(item.id)
                savedArray.append(item.id)
            }
            db.save(items: savedItems)
        }
    }


struct FavView: View {
    @StateObject private var vm = ViewModel()

    var body: some View {
        VStack {
            
            List {
                var x = print("testing",vm.savedArray)//this only prints once at the start
                ForEach($vm.savedArray, id: \.self) { string in
                    let item = vm.db.returnItem(input: string.wrappedValue)
                    HStack {
                        VStack(alignment: .leading) {
                            Text(item.title)
                                .font(.headline)
                            
                            Text(item.description)
                                .font(.subheadline)
                        }
                        Spacer()
                        Image(systemName: vm.contains(item) ? "bookmark.fill" : "bookmark")
                            .foregroundColor(.blue)
                            .onTapGesture {
                                vm.toggleFav(item: item)
                            }
                    }
                }
            }
            .cornerRadius(10)
        }
    }
}


Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
68
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

в ForEach вы используете символ $ для доступа к savedArray вам нужно использовать сам vm

struct FavView: View {
    @StateObject private var vm = ViewModel()
    
    var body: some View {
        VStack {
            
            List {
  
                ForEach($vm.savedArray, id: \.self) { string in //< here $vm.savedArray not vm.$savedArray
                    let item = vm.db.returnItem(input: string)
                    HStack {
                        VStack(alignment: .leading) {
                            Text(item.title)
                                .font(.headline)
                            
                            Text(item.description)
                                .font(.subheadline)
                        }
                        Spacer()
                        Image(systemName: vm.contains(item) ? "bookmark.fill" : "bookmark")
                            .foregroundColor(.blue)
                            .onTapGesture {
                                vm.toggleFav(item: item)
                            }
                    }
                }
            }
            .cornerRadius(10)
        }
    }
}

это должно работать.

Я только что изменил его, и он дает мне ошибку «Невозможно преобразовать значение типа« Binding <String> »в ожидаемый тип аргумента« String »» в строке vm.db.returnItem(), которая принимает ввод String. Я отредактировал, чтобы включить эту функцию. Спасибо!

Linda Xue 31.10.2022 13:21

если «Published<[String]>.Publisher» соответствует «RandomAccessCollection». исправлено, пожалуйста, примите мой ответ

Wahid Tariq 31.10.2022 13:40

поделитесь скриншотом кода с ошибкой, чтобы было понятно

Wahid Tariq 31.10.2022 13:46

Я исправил проблему, используя .wrappedValue, поэтому мой код теперь работает, но похоже, что настоящая причина, по которой мой код не работает, заключается в том, что даже при том, что saveArray изменен, FavView не инициализируется повторно, когда он изменяется, поэтому он отображает старый значения. Когда я перезапускаю программу, FavView перестраивается. Есть ли способ восстановить FavView всякий раз, когда я редактирую saveArray? Спасибо!

Linda Xue 31.10.2022 22:19

Другие вопросы по теме