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

将视图作为参数传入另一视图时@AppStorage无法更新问题问询

SwiftUI中@AppStorage作为视图参数传递时的更新问题

问题复现

我定义了一个接收视图作为参数的ListItem视图:

struct ListItem<Content: View>: View {
  
  let title: String
  let suffix: () -> Content   // 接收视图
  
  var body: some View {
    HStack {
      Text(title)
      Spacer()
      suffix()                // 渲染传入的视图
    }
  }
}

接着我把包含动态@AppStorage内容的视图传入其中:

struct MyList: View {
  
  @AppStorage("counter") var counter: Int = 0   // 绑定UserDefaults中的值
  
  var body: some View {
    ListItem(title: "Counter") {
      Text("\(counter)")                        // 传入带@AppStorage绑定的文本视图
    }
    Button("Increment") {
      counter += 1                              // 修改UserDefaults中的值
    }
  }
}

此时点击"Increment"按钮,ListItem里显示的数值不会实时更新——只有当视图触发重渲染(比如子视图刷新、onAppear触发)时,才会显示新值。但如果用@State或@Environment绑定的值,就不会出现这个问题。

疑问

这是@AppStorage的预期行为还是Bug?还有哪些传递视图参数的场景会导致状态过期?

解决方法

我尝试用ViewModifier实现了相同的布局逻辑:

struct ListItemizer: ViewModifier {
  
  let title: String
  
  func body(content: Content) -> some View {
    HStack {
      Text(title)
      Spacer()
      content                                 // 渲染原视图
    }
  }
}

然后把这个修饰符应用到包含动态内容的视图上:

struct MyList: View {
  
  @AppStorage("counter") var counter: Int = 0
  
  var body: some View {
    Text("\(counter)")
      .modifier(
        ListItemizer(title: "Counter")         // 为带动态绑定的文本视图添加修饰符
      )
    Button("Increment") {
      counter += 1
    }
  }
}

这时点击按钮,数值会立即更新,符合预期。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 13:02:06