基于@AppStorage实现多视图地标收藏与列表高亮问题咨询
问题分析与解决方案
当前代码的核心问题是所有地标共用同一个@AppStorage键"isFavorite",导致收藏状态是全局共享的,而非针对单个地标,这直接造成列表无法正确识别每个地标的收藏状态。
修复步骤:
为每个地标生成唯一存储键
利用地标唯一的id拼接专属存储键(比如"favorite_\(landmark.id)"),确保每个地标的收藏状态独立存储。修改收藏按钮组件
让FavoriteButton接收外部传入的存储键,不再使用固定键值:
struct FavoriteButton: View { let storageKey: String @AppStorage var isFavorite: Bool = false init(storageKey: String) { self.storageKey = storageKey _isFavorite = AppStorage(wrappedValue: false, storageKey) } var body: some View { Button { isFavorite.toggle() } label: { Label("Toggle Favorite", systemImage: isFavorite ? "star.fill" : "star") .labelStyle(.iconOnly) .foregroundColor(isFavorite ? .yellow : .gray) } } }
- 更新地标详情视图
在LandmarkDetail中传入当前地标的唯一存储键:
struct LandmarkDetail: View { let landmark: Landmark // 补充原代码遗漏的属性定义 var body: some View { ScrollView { VStack(alignment: .leading) { HStack { Text(landmark.name) .font(.title) FavoriteButton(storageKey: "favorite_\(landmark.id)") } } } } }
- 修复列表行的高亮逻辑
在LandmarkRow中使用对应地标的存储键获取收藏状态,替换原来的landmark.isFavorite判断:
struct LandmarkRow: View { var landmark: Landmark @AppStorage("favorite_\(landmark.id)") var isFavorite: Bool = false var body: some View { HStack { landmark.image .resizable() .frame(width: 50, height: 50) .cornerRadius(8) Text(landmark.name) Spacer() if isFavorite { Image(systemName: "star.fill") .foregroundColor(.yellow) } } } }
补充说明
- 确保你的
Landmark模型包含唯一的id属性(通常从JSON加载的模型会自带该属性) - 修改后每个地标的收藏状态会独立保存在本地存储中,列表能正确高亮已收藏的条目
内容的提问来源于stack exchange,提问作者efranka
相关产品推荐
相关产品推荐

