为什么我的 SwiftUI 视图没有更新? MVVM架构

问题描述 投票:0回答:1

我有两个 Swift UI 视图,

CategoriesListView
CategoryView.
CategoriesListView
的工作方式有点像导航菜单,
CategoryView
是一个可以点击的视图。我正在尝试以下操作:

  • 除第一个类别外,所有类别一开始均未突出显示。
  • 如果用户选择列表中的某个类别(选择
    CategoryView
    ),该类别将显示突出显示的图像
  • 之前选择的任何类别都不会突出显示并显示未突出显示的图像

不幸的是,一旦点击某些内容,类别视图就不会改变。我必须在视图模型中做一些事情吗?我对 SwiftUI 还很陌生,并且仍在学习很多东西

我的看法:

struct CategoriesListView: View {
    @Environment(CategoriesListViewModel.self) var categoriesListViewModel
    
    var selectedIndex: Int { categoriesListViewModel.categories.firstIndex(where: {
            $0.isSelected == true
        }) ?? 0
    }
    
    var body: some View {
        @Bindable var categoriesListViewModel = categoriesListViewModel
        ScrollView(.horizontal) {
            HStack(alignment: .top, spacing: 12) {
                Spacer()
                // With each category in the categories list view model, create a category view. If the category view gets tapped, change that view to be the selected image. the previously selected view shows an unselected image.
                ForEach(Array(categoriesListViewModel.categories.enumerated()), id: \.offset) { index, element in
                    CategoryView(categoryViewModel: $categoriesListViewModel.categories[index]).onTapGesture {
                        categoriesListViewModel.categories[selectedIndex].isSelected = false
                        categoriesListViewModel.categories[index].isSelected = true
                        CategoryView(categoryViewModel: $categoriesListViewModel.categories[index])
                    }
                }
            }
        }
    }
}

struct CategoryView: View {
    @Binding var categoryViewModel: CategoryViewModel
    
    var body: some View {
        if categoryViewModel.isSelected {
            categoryViewModel.category.highlightedIconImage
        } else {
            categoryViewModel.category.iconImage
        }
    }
}

我的视图模型:


@Observable
class CategoriesListViewModel {
    var categories: [CategoryViewModel] = []
    var currentSelection: Int = 0
    var previousSelection: Int? = nil
    
    init(categories: [CategoryViewModel], currentSelection: Int, previousSelection: Int? = nil) {
        self.categories = setCategoriesToShow()
        self.currentSelection = currentSelection
        self.previousSelection = previousSelection
    }
    
    func setCategoriesToShow() -> [CategoryViewModel] {
        var categoriesToShow = [CategoryViewModel]()
        let resortCategory = Category(
            identifier: "a",
            title: "Resort",
            outfits: [],
            iconImage: Image("ResortUnselected"),
            highlightedIconImage: Image("ResortSelected")
        )
        
        var europeCategory = Category(
            identifier: "b",
            title: "Europe",
            outfits: [],
            iconImage: Image("EuropeUnselected"),
            highlightedIconImage: Image("EuropeSelected")
        )
        
        var brunchCategory = Category(
            identifier: "c",
            title: "Brunch",
            outfits: [],
            iconImage: Image("BrunchUnselected"),
            highlightedIconImage: Image("BrunchSelected")
        )
        
        var athleisureCategory = Category(
            identifier: "d",
            title: "Athleisure",
            outfits: [],
            iconImage: Image("AthleisureUnselected"),
            highlightedIconImage: Image("AthleisureSelected")
        )
        
        var workCategory = Category(
            identifier: "e",
            title: "Work",
            outfits: [],
            iconImage: Image("WorkUnselected"),
            highlightedIconImage: Image("WorkSelected")
        )
        
        categoriesToShow.append(CategoryViewModel(category: resortCategory, isSelected: true))
        categoriesToShow.append(CategoryViewModel(category: europeCategory, isSelected: false))
        categoriesToShow.append(CategoryViewModel(category: brunchCategory, isSelected: false))
        categoriesToShow.append(CategoryViewModel(category: athleisureCategory, isSelected: false))
        categoriesToShow.append(CategoryViewModel(category: workCategory, isSelected: false))
        
        return categoriesToShow
    }
}

class CategoryViewModel: ObservableObject, Identifiable {
    var category: Category
    var isSelected: Bool
    
    init(category: Category, isSelected: Bool) {
        self.category = category
        self.isSelected = isSelected
    }
}
swift xcode swiftui mvvm
1个回答
0
投票

请勿混合

ObservableObject
@Observable
(例如您的 CategoryViewModel)。 另外,当您使用
Identifiable
时,您需要有
let id...

尝试用这种方法清理

ForEach
中的
CategoriesListView
:

 ForEach(Array(categoriesListViewModel.categories.enumerated()), id: \.offset) { index, element in
     CategoryView(categoryViewModel: $categoriesListViewModel.categories[index])
         .onTapGesture {
         categoriesListViewModel.categories[selectedIndex].isSelected = false
         categoriesListViewModel.categories[index].isSelected = true
     }
 }

@Observable
 class CategoryViewModel: Identifiable {
     let id = UUID()
     var category: Category
     var isSelected: Bool
     
     init(category: Category, isSelected: Bool) {
         self.category = category
         self.isSelected = isSelected
     }
 }
© www.soinside.com 2019 - 2024. All rights reserved.