视图未在类别菜单项选择 SwiftUI 上更新
View is not updating on Category Menu Item Selection SwiftUI
这是我的第一个 SwiftUI 应用程序。我做了很多搜索,但找不到解决方案。
我想展示不同类别的产品。为此,我有顶部栏水平滚动菜单。选择任何类别时,我想显示每个类别的产品。当加载第一类产品显示正确,但选择任何其他类别时,产品不会相应更新。但是,当我导航到任何其他视图并返回到该视图时,产品显示正确。
我试过的
我尝试了不同的视图来显示产品,例如 List/ScrollView。运气不好。
这是我的视图的完整代码
struct ProductListView: View {
@State var data:[Product]
@State private var categoryItems:[Product] = []
@State private var uniqueCategories:[Product] = []
@State private var numberOfRows:Int = 0
@State private var selectedItem:Int = 0
@State private var image:UIImage?
@EnvironmentObject var authState: AuthenticationState
@ViewBuilder
var body: some View {
NavigationView{
VStack{
ScrollView(.horizontal, showsIndicators: false) {
HStack {
ForEach(0..<self.data.removingDuplicates(byKey: { [=10=].category }).count) { i in
Text(self.data.removingDuplicates(byKey: { [=10=].category })[i].category)
.underline(self.selectedItem == i ? true:false, color: Color.orange)
.foregroundColor(self.selectedItem == i ? Color.red:Color.black)
//.border(Color.gray, width: 2.0)
.overlay(
RoundedRectangle(cornerRadius: 0.0)
.stroke(Color.init(red: 236.0/255.0, green: 240.0/255.0, blue: 241.0/255.0), lineWidth: 1).shadow(radius: 5.0)
).padding(.horizontal)
//.shadow(radius: 5.0)
.onTapGesture {
self.selectedItem = i
_ = self.getSelectedCategoryProducts()
print("Category Items New Count: \(self.categoryItems.count)")
}
Spacer()
Divider().background(Color.orange)
}
}
}
.frame(height: 20)
Text("My Products").foregroundColor(Color.red).padding()
Spacer()
if(self.data.count == 0){
Text("You didn't add any product yet.")
}
if (self.categoryItems.count>0){
ScrollView(.vertical){
ForEach(0..<Int(ceil(Double(self.categoryItems.count)/2.0)), id: \.self){ itemIndex in
return HStack() {
NavigationLink(destination:ProductDetailView(index: self.computeIndexes(currentIndex: itemIndex,cellNo: 1), data: self.categoryItems, image: UIImage())){
ProductTile(index: self.computeIndexes(currentIndex: itemIndex, cellNo: 1), data: self.categoryItems, image: UIImage())
}
NavigationLink(destination:ProductDetailView(index: self.computeIndexes(currentIndex: itemIndex,cellNo: 2), data: self.categoryItems, image: UIImage())){
ProductTile(index: self.computeIndexes(currentIndex: itemIndex, cellNo: 2), data: self.categoryItems, image: UIImage())
}
}.padding(.horizontal)
}
}.overlay(
RoundedRectangle(cornerRadius: 10.0)
.stroke(Color.init(red: 236.0/255.0, green: 240.0/255.0, blue: 241.0/255.0), lineWidth: 1).shadow(radius: 5.0)
)
}
}
}
.onAppear(perform: {
_ = self.getSelectedCategoryProducts()
//print("Loading updated products....")
if (self.authState.loggedInUser != nil){
FireStoreManager().loadProducts(userId: self.authState.loggedInUser!.uid) { (isSuccess, data) in
self.data = data
}
}
})
.padding()
}
func populateUniqueCategories() -> [Product] {
let uniqueRecords = self.data.reduce([], {
[=10=].contains() ? [=10=] : [=10=] + []
})
print("Unique Items: \(uniqueRecords)")
return uniqueRecords
}
func getSelectedCategoryProducts() -> [Product] {
var categoryProducts:[Product] = []
self.data.forEach { (myProduct) in
if(myProduct.category == self.populateUniqueCategories()[selectedItem].category){
categoryProducts.append(myProduct)
}
}
self.categoryItems.removeAll()
self.categoryItems = categoryProducts
return categoryProducts
}
func computeIndexes(currentIndex:Int, cellNo:Int) -> Int {
var resultedIndex:Int = currentIndex
if (cellNo == 1){
resultedIndex = resultedIndex+currentIndex
print("Cell 1 Index: \(resultedIndex)")
}else{
resultedIndex = resultedIndex + currentIndex + 1
print("Cell 2 Index: \(resultedIndex)")
}
return resultedIndex
}
}
这是数组扩展
extension Array {
func removingDuplicates<T: Hashable>(byKey key: (Element) -> T) -> [Element] {
var result = [Element]()
var seen = Set<T>()
for value in self {
if seen.insert(key(value)).inserted {
result.append(value)
}
}
return result
}
}
如果你能帮我解决这个问题,我将不胜感激。
最好的问候
原因是在使用静态范围 ForEach 构造函数时,它不希望有任何更改,这是设计使然,因此不会更新。
所以不用像
ForEach(0..<self.data.removingDuplicates(byKey: { [=10=].category }).count) { i in
^^^^^^ range !!
和
ForEach(0..<Int(ceil(Double(self.categoryItems.count)/2.0)), id: \.self){
^^^^ range
需要使用直接数据容器,如
ForEach(self.data.removingDuplicates(byKey: { [=12=].category }), id: \.your_product_id) { product in
^^^^^^^^^ array
注意:迭代时如果需要索引,可以使用.enumerated()
容器,eg:
我想展示不同类别的产品。为此,我有顶部栏水平滚动菜单。选择任何类别时,我想显示每个类别的产品。当加载第一类产品显示正确,但选择任何其他类别时,产品不会相应更新。但是,当我导航到任何其他视图并返回到该视图时,产品显示正确。
我试过的
我尝试了不同的视图来显示产品,例如 List/ScrollView。运气不好。
这是我的视图的完整代码
struct ProductListView: View {
@State var data:[Product]
@State private var categoryItems:[Product] = []
@State private var uniqueCategories:[Product] = []
@State private var numberOfRows:Int = 0
@State private var selectedItem:Int = 0
@State private var image:UIImage?
@EnvironmentObject var authState: AuthenticationState
@ViewBuilder
var body: some View {
NavigationView{
VStack{
ScrollView(.horizontal, showsIndicators: false) {
HStack {
ForEach(0..<self.data.removingDuplicates(byKey: { [=10=].category }).count) { i in
Text(self.data.removingDuplicates(byKey: { [=10=].category })[i].category)
.underline(self.selectedItem == i ? true:false, color: Color.orange)
.foregroundColor(self.selectedItem == i ? Color.red:Color.black)
//.border(Color.gray, width: 2.0)
.overlay(
RoundedRectangle(cornerRadius: 0.0)
.stroke(Color.init(red: 236.0/255.0, green: 240.0/255.0, blue: 241.0/255.0), lineWidth: 1).shadow(radius: 5.0)
).padding(.horizontal)
//.shadow(radius: 5.0)
.onTapGesture {
self.selectedItem = i
_ = self.getSelectedCategoryProducts()
print("Category Items New Count: \(self.categoryItems.count)")
}
Spacer()
Divider().background(Color.orange)
}
}
}
.frame(height: 20)
Text("My Products").foregroundColor(Color.red).padding()
Spacer()
if(self.data.count == 0){
Text("You didn't add any product yet.")
}
if (self.categoryItems.count>0){
ScrollView(.vertical){
ForEach(0..<Int(ceil(Double(self.categoryItems.count)/2.0)), id: \.self){ itemIndex in
return HStack() {
NavigationLink(destination:ProductDetailView(index: self.computeIndexes(currentIndex: itemIndex,cellNo: 1), data: self.categoryItems, image: UIImage())){
ProductTile(index: self.computeIndexes(currentIndex: itemIndex, cellNo: 1), data: self.categoryItems, image: UIImage())
}
NavigationLink(destination:ProductDetailView(index: self.computeIndexes(currentIndex: itemIndex,cellNo: 2), data: self.categoryItems, image: UIImage())){
ProductTile(index: self.computeIndexes(currentIndex: itemIndex, cellNo: 2), data: self.categoryItems, image: UIImage())
}
}.padding(.horizontal)
}
}.overlay(
RoundedRectangle(cornerRadius: 10.0)
.stroke(Color.init(red: 236.0/255.0, green: 240.0/255.0, blue: 241.0/255.0), lineWidth: 1).shadow(radius: 5.0)
)
}
}
}
.onAppear(perform: {
_ = self.getSelectedCategoryProducts()
//print("Loading updated products....")
if (self.authState.loggedInUser != nil){
FireStoreManager().loadProducts(userId: self.authState.loggedInUser!.uid) { (isSuccess, data) in
self.data = data
}
}
})
.padding()
}
func populateUniqueCategories() -> [Product] {
let uniqueRecords = self.data.reduce([], {
[=10=].contains() ? [=10=] : [=10=] + []
})
print("Unique Items: \(uniqueRecords)")
return uniqueRecords
}
func getSelectedCategoryProducts() -> [Product] {
var categoryProducts:[Product] = []
self.data.forEach { (myProduct) in
if(myProduct.category == self.populateUniqueCategories()[selectedItem].category){
categoryProducts.append(myProduct)
}
}
self.categoryItems.removeAll()
self.categoryItems = categoryProducts
return categoryProducts
}
func computeIndexes(currentIndex:Int, cellNo:Int) -> Int {
var resultedIndex:Int = currentIndex
if (cellNo == 1){
resultedIndex = resultedIndex+currentIndex
print("Cell 1 Index: \(resultedIndex)")
}else{
resultedIndex = resultedIndex + currentIndex + 1
print("Cell 2 Index: \(resultedIndex)")
}
return resultedIndex
}
}
这是数组扩展
extension Array {
func removingDuplicates<T: Hashable>(byKey key: (Element) -> T) -> [Element] {
var result = [Element]()
var seen = Set<T>()
for value in self {
if seen.insert(key(value)).inserted {
result.append(value)
}
}
return result
}
}
如果你能帮我解决这个问题,我将不胜感激。 最好的问候
原因是在使用静态范围 ForEach 构造函数时,它不希望有任何更改,这是设计使然,因此不会更新。
所以不用像
ForEach(0..<self.data.removingDuplicates(byKey: { [=10=].category }).count) { i in
^^^^^^ range !!
和
ForEach(0..<Int(ceil(Double(self.categoryItems.count)/2.0)), id: \.self){
^^^^ range
需要使用直接数据容器,如
ForEach(self.data.removingDuplicates(byKey: { [=12=].category }), id: \.your_product_id) { product in
^^^^^^^^^ array
注意:迭代时如果需要索引,可以使用.enumerated()
容器,eg: