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

SwiftUI使用@State管理日历选中日期时随机字符串重复生成问题咨询

问题判断

你的判断完全正确。

@State 属性发生变更时,会触发其所属的整个 View 结构体的 body 重新渲染。你的 Summary 是 Reservations 视图的内部方法,和 selectedDate 同属一个视图层级,因此 selectedDate 更新后整个 Summary 都会重绘,调用随机字符串生成函数,导致 ID 每次都变化。

解决方案

有两种常用的低成本改造方案可以解决这个问题:

方案1:将随机字符串存入独立的@State属性,仅生成一次

因为随机ID只需要在页面初始化时生成一次,你可以单独声明一个@State存储该值,避免每次重绘重复调用生成函数:

struct Reservations: View {
    @Environment(\.calendar) private var calendar
    @State private var selectedDate: Date = Self.now
    // 新增存储随机ID的State
    @State private var randomID: String = ""
    private static var now = Date()
    
    var body: some View {
        Summary()
        ReservationsCalendar()
            // 页面首次出现时生成一次随机ID
            .onAppear {
                randomID = generateRandomString(length: 7).uppercased()
            }
    }
}

然后把 Summary 里的 generateRandomString 调用替换为 randomID 即可。

方案2:拆分视图,隔离不需要刷新的组件

你可以把随机ID的展示部分封装为独立的子View,只要这个子View的输入参数不包含 selectedDate,SwiftUI 就会判断它的依赖没有变化,不会在 selectedDate 更新时重绘该子View:

// 新增独立的随机ID视图
struct RandomIDView: View {
    private let randomID: String
    init(length: Int) {
        let letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
        randomID = String((0..<length).map{ _ in letters.randomElement()! }).uppercased()
    }
    
    var body: some View {
        Text(randomID)
            .foregroundColor(.yellow)
            .padding(.horizontal, 10)
            .frame(height: 25)
            .background(
                Capsule()
                    .fill(.black.opacity(0.2))
            )
    }
}

替换原 Summary 里的对应代码即可:

Text("ID").foregroundColor(.white)
RandomIDView(length: 7)

跨视图修改值的替代方案

如果需要修改不在同一视图的单个值,根据视图层级复杂度选择即可:

  • 父子视图直接传值:用 @Binding 即可,你当前 ReservationsCal 用 @Binding 接收 selectedDate 的方案本身是正确的,没有问题
  • 多层级/多无关视图共享值:iOS 17+ 用 @Observable 配合环境变量注入,iOS 16及以下用 @StateObject + @EnvironmentObject 实现全局共享状态即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 22:15:04