You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI时区选择组件单选异常:如何实现单个元素勾选

问题:点击任意时区项时,所有项的收藏状态同时切换

原代码实现

主视图结构

struct TimeZoneView: View {
    @State private var favorite = false
    @State private var timezone: String = ""

    private var timeZoneIdentifiers = TimeZone.knownTimeZoneIdentifiers

    var body: some View {
        ZStack {
            Color.white
                .ignoresSafeArea()
            ScrollView(showsIndicators: false, content: {
                VStack(spacing: 25) {
                    selection
                    Spacer()
                }
            })
        }
    }
}

视图组件函数

func createSelection(
    title: String,
    clicked: (() -> Void)?,
    favorite: Bool
) -> some View {
    VStack {
        Button(action: {
            clicked?()
        }, label: {
            VStack(spacing: 10) {
                VStack {
                    HStack {
                        Text(title)
                            .font(.custom(.semiBold, size: 16))
                            .foregroundColor(.theme.appBlack)
                        Spacer()
                        if favorite {
                            Image.app.addPurple
                                .resizable()
                                .frame(width: 16,height: 16)
                        }
                    }
                    .padding(20)
                }
                .overlay(
                    RoundedRectangle(cornerRadius: 10)
                        .stroke(Color.theme.grayProfileText, lineWidth: 0.5)
                )
                .padding([.leading,.trailing], 20)
            }
        })
    }
}

列表遍历视图

var selection: some View {
    VStack(spacing: 10) {
        ForEach(timeZoneIdentifiers, id: \.self) { zone in
            let temp = zone.components(separatedBy: "/")
            if temp.count >= 2 {
                let cityName = temp[1].replacingOccurrences(of: "_", with: " ")
                createSelection(title: zone, clicked: {
                    timezone = cityName
                    favorite.toggle()
                }, favorite: favorite)
            }
        }
    }
}

问题现象

点击任意时区项时,所有项的收藏图标都会同步切换,无法单独标记某一个时区为收藏状态。

问题原因

当前使用单个@State private var favorite = false变量控制所有时区项的收藏状态,所有列表项都绑定同一个布尔值,因此点击任意项触发favorite.toggle()时,所有项的favorite参数都会同步变化。

解决方案

需要为每个时区单独维护收藏状态,改用**Set**存储已收藏的时区ID,这样可以独立跟踪每个时区的收藏状态:

修改后的完整代码

struct TimeZoneView: View {
    // 用Set存储已收藏的时区ID,每个时区独立管理状态
    @State private var favoriteTimeZones: Set<String> = []
    @State private var timezone: String = ""

    private var timeZoneIdentifiers = TimeZone.knownTimeZoneIdentifiers

    var body: some View {
        ZStack {
            Color.white
                .ignoresSafeArea()
            ScrollView(showsIndicators: false, content: {
                VStack(spacing: 25) {
                    selection
                    Spacer()
                }
            })
        }
    }

    func createSelection(
        title: String,
        timezoneId: String,
        clicked: (() -> Void)?,
        isFavorite: Bool
    ) -> some View {
        VStack {
            Button(action: {
                clicked?()
                // 切换当前时区的收藏状态
                if isFavorite {
                    favoriteTimeZones.remove(timezoneId)
                } else {
                    favoriteTimeZones.insert(timezoneId)
                }
            }, label: {
                VStack(spacing: 10) {
                    VStack {
                        HStack {
                            Text(title)
                                .font(.custom(.semiBold, size: 16))
                                .foregroundColor(.theme.appBlack)
                            Spacer()
                            if isFavorite {
                                Image.app.addPurple
                                    .resizable()
                                    .frame(width: 16,height: 16)
                            }
                        }
                        .padding(20)
                    }
                    .overlay(
                        RoundedRectangle(cornerRadius: 10)
                            .stroke(Color.theme.grayProfileText, lineWidth: 0.5)
                    )
                    .padding([.leading,.trailing], 20)
                }
            })
        }
    }

    var selection: some View {
        VStack(spacing: 10) {
            ForEach(timeZoneIdentifiers, id: \.self) { zone in
                let temp = zone.components(separatedBy: "/")
                if temp.count >= 2 {
                    let cityName = temp[1].replacingOccurrences(of: "_", with: " ")
                    // 检查当前时区是否在收藏Set中
                    let isFavorite = favoriteTimeZones.contains(zone)
                    createSelection(title: zone, timezoneId: zone, clicked: {
                        timezone = cityName
                    }, isFavorite: isFavorite)
                }
            }
        }
    }
}

关键修改点

  1. 将单个favorite布尔变量替换为favoriteTimeZones: Set<String>,存储所有已收藏的时区ID
  2. 在createSelection中新增timezoneId参数,用于标识当前操作的时区
  3. 点击按钮时,根据当前时区是否在收藏Set中,执行添加/移除操作
  4. 每个列表项的收藏状态通过favoriteTimeZones.contains(zone)单独判断,实现独立控制

内容的提问来源于stack exchange,提问作者Oleksandr

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 02:19:59