SwiftUI - 使用按钮切换“收藏”动态项目

Posted

技术标签:

【中文标题】SwiftUI - 使用按钮切换“收藏”动态项目【英文标题】:SwiftUI - Using a Button to toggle "Favoriting" a dynamic item 【发布时间】:2019-12-05 16:39:50 【问题描述】:

我是 SwiftUI 和数据管理的新手。如上所述,我正在尝试使用一个按钮,该按钮允许用户切换收藏他们正在查看的项目。我正在尝试将该值写入 UserDefaults。

我已经设法破解了一个版本,其中按钮成功写入和删除对象,但问题是它不会切换视图。仅当您离开视图后再次导航回该项目时,该按钮才会更新。以下是我目前拥有的代码。我的愿望是在用户收藏或取消收藏某个项目时直观地切换按钮。

import SwiftUI

struct ItemDetail: View 
var productID: Int
var productTitle: String
var itemURL: String
var productDescription: String
var productPrice: Double
var venueTitle: String
var newStatus: Bool
var diningPlan: Bool
var kidFriendly: Bool
var vegetarian: Bool
var glutenFree: Bool
var featuredProduct: Bool
var containsAlcohol: Bool

var body: some View 
    GeometryReader  geometry in
        VStack(alignment: .leading) 
            LoadableImageView(with: self.itemURL)
                .aspectRatio(contentMode: .fit)
                .cornerRadius(6)
            HStack(alignment: .top) 
                Text(self.productTitle)
                    .font(.system(size: 22))
                    .fontWeight(.bold)
                Spacer()
                Text("$\(self.productPrice, specifier: "%.2f")")
                    .font(.system(size: 20))
                    .fontWeight(.bold)
                    .padding(.leading, 50)
            
            HStack 
                Text(self.productDescription)
                    .font(.system(size: 16))
                    .foregroundColor(Color("bodyText"))
                    .frame(width: geometry.size.width / 1.5, alignment: .leading)
                    .fixedSize(horizontal: false, vertical: true)
                Spacer()
            .padding(.top, 5)
            VStack(alignment: .leading) 
                HStack(alignment: .top, spacing: 8) 
                    if(self.newStatus) 
                        Image("tag-new")
                            .renderingMode(.original)
                    
                    if(self.diningPlan) 
                        Image("tag-ddp")
                            .renderingMode(.original)
                    
                    if(self.kidFriendly) 
                        Image("tag-kidfriendly")
                            .renderingMode(.original)

                    
                    if(self.vegetarian) 
                        Image("tag-vegetarian")
                            .renderingMode(.original)
                    
                    if(self.glutenFree) 
                        Image("tag-gluten")
                            .renderingMode(.original)
                    
                    if(self.featuredProduct) 
                        Image("tag-featured")
                            .renderingMode(.original)
                    
                    if(self.containsAlcohol) 
                        Image("tag-alcohol")
                            .renderingMode(.original)
                    
                .padding(.top, 5)
                HStack 
                    Text("Located At:")
                        .font(.system(size: 16))
                        .fontWeight(.semibold)
                    Text(self.venueTitle)
                        .font(.system(size: 16))
                        .foregroundColor(Color("bodyText"))
                    Spacer()
                .padding(.top, 50)
            
            Spacer()
            HStack 
                if UserDefaults.standard.object(forKey: self.productTitle) != nil 
                    Button(action: 
                        UserDefaults.standard.removeObject(forKey: self.productTitle)
                        print("Unfavorited \(self.productTitle)")
                        self.isFavorite = ""
                        print("\(self.isFavorite)")
                    ) 
                        Text("Favorite")
                            .padding()
                    .frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: 50)
                        .foregroundColor(.white)
                        .background(Color.red)
                        .cornerRadius(8)
                 else 
                    Button(action: 
                        UserDefaults.standard.set("Favorite", forKey: self.productTitle)
                        print("Added Favorite \(self.productTitle)")
                        self.isFavorite = "Favorite"
                        print("\(self.isFavorite)")
                    ) 
                        Text("Add to Favorites")
                            .fontWeight(.semibold)
                            .foregroundColor(.red)
                            .padding()
                            .frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: 50)
                            .overlay (
                                RoundedRectangle(cornerRadius: 8)
                                    .stroke(Color.red, lineWidth: 2)
                        )
                    
                
            .padding(.bottom)
        .padding(.all)
            .navigationBarTitle(Text("Item Details"))
        
    

【问题讨论】:

【参考方案1】:

isFavorite 应该是 SwiftUI 可以观察到的变化。例如它可能是:

@State var isFavorite = false

@Binding var isFavorite: Bool

对于您的情况,最好使用Combine 并构建一个包含有关该项目的所有信息的ViewModel。然后您应该在模型中发布更改,任何View 观察该更改将自动刷新。

This search result 可以帮助您进一步了解CombineSwiftUI

请注意,UserDefaults 不是存储此类数据的好地方

【讨论】:

以上是关于SwiftUI - 使用按钮切换“收藏”动态项目的主要内容,如果未能解决你的问题,请参考以下文章

如何在 SwiftUI 中动态隐藏导航返回按钮

如何在切换 SwiftUI 中使用 json 属性?

添加 ViewModel 后,SwiftUI 视图未在按钮切换上更新

iOS:如何使用侧边菜单、SwiftUI 切换视图

在 SwiftUI 中动态更改动画的持续时间

SwiftUI:切换和按钮的奇怪错误