我正在嘗試根據用戶是否切換收藏按鈕來創建一個更新的視圖。我希望重建整個視圖,以便在更改值陣列時顯示值陣列。在視圖內部,for each 回圈應該顯示陣列中的每個值。
每次更改 savedArray 時我想要更新的視圖是 FavView。但是,當我嘗試使用 foreach 回圈顯示每個值時 saveArray(我將其創建為 @Published 以便視圖可以重建),它給了我錯誤 Generic struct 'ForEach' requires that 'Published<[String]>. Publisher' 符合 'RandomAccessCollection'。我很困惑,因為我認為字串陣列可以用于每個回圈。這不是真的嗎?如何回圈通過 @Published 陣列?謝謝!這是我的 savedArray(在 ViewModel 中)的代碼和我想用 for each 顯示它的 FavView。
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 {
ForEach($vm.savedArray, id: \.self) { string in
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)
}
}
}//my error is here at the for each
}
.cornerRadius(10)
}
}
}
//the returnItem function(it's in another file) and accepts a String
func returnItem(input: String) -> Item{
let vm = ViewModel()
let test = cityClass()
let temp = test.getConvert(input: input)//a datafrime slice
let state: String = (temp["state", String.self].first ?? "There was an error") ?? "There was an error"
let zip = ((temp["zip", String.self].first ) ?? "There was an error" ) ?? "There was an error"
let id = input
let title: String = (temp["primary_city", String.self].first ?? "There was an error") ?? "There was an error"
let description = "\(state) \(zip)"
if(vm.contains(Item(id: id, title: title, description: description, isFaved: true)) == false){
temptList.append(Item(id: id, title: title, description: description, isFaved: true))
}
print("TEMPLIST", temptList)
return Item(id: id, title: title, description: description, isFaved: true)
}
uj5u.com熱心網友回復:
在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)
}
}
}
這應該有效。
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/523613.html
