首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

表单中的SwiftUI - ForEach不会更新内容,即使它被正确存储

基础概念

SwiftUI 是苹果推出的一个声明式 UI 框架,用于构建 macOS、iOS、watchOS 和 tvOS 应用程序。ForEach 是 SwiftUI 中的一个视图构造器,用于遍历集合(如数组)并渲染每个元素。

问题原因

ForEach 不会更新内容的原因通常是因为 SwiftUI 的依赖跟踪机制。SwiftUI 只会在其依赖发生变化时重新渲染视图。如果集合本身没有发生变化(例如,数组的引用没有变,只是数组内部元素变了),ForEach 就不会重新渲染。

解决方法

  1. 确保集合是可变的:使用可变数组,而不是不可变数组。
  2. 使用 @State@ObservedObject:确保集合的变化能够被 SwiftUI 检测到。

示例代码

假设我们有一个简单的表单,其中包含一个文本字段和一个按钮,点击按钮会向数组中添加一个新的字符串。

代码语言:txt
复制
import SwiftUI

struct ContentView: View {
    @State private var items = ["Item 1", "Item 2"]
    
    var body: some View {
        VStack {
            ForEach(items.indices, id: \.self) { index in
                Text(items[index])
            }
            
            Button(action: {
                items.append("New Item")
            }) {
                Text("Add Item")
            }
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

在这个示例中,items 是一个 @State 属性包装的可变数组。每次点击按钮时,items 数组都会被修改,这会导致 ForEach 重新渲染。

参考链接

通过这种方式,你可以确保 ForEach 能够正确地响应集合的变化并更新 UI。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

SwiftUI geometryGroup() 指南:从原理到实践

访问我博客 www.fatbobman.com[1] 可以获得更好阅读体验以及最新更新内容。...您可以阅读 掌握 Transaction,实现 SwiftUI 动画精准控制[5] 和 SwiftUI 动画机制了解更多内容[6]。...当创建黄色圆形时,即使 show 状态已改变,父视图(frame)仍会持续传递其当前几何信息( 动画中)。这让黄色圆形能够获得正确布局位置。...geometryGroup() 确保子视图在统一几何信息环境,以实现预期布局效果。它为子视图提供了一个连续几何信息更新过程。 总结上述条件后,我们就很容易创建出其它会导致意外行为代码。...对于 iOS 16,在文字变化较多且较大情况下,应尽量避免在父视图几何信息调整时切换文字内容。 总结 在本文中,我们深入探讨了 SwiftUI geometryGroup() 重要性和实用性。

27210

SwiftUI 与 Core Data —— 安全地响应数据

Todo 代码访问我博客 www.fatbobman.com[5] 可以获得更好阅读体验以及最新更新内容。...从另一个角度来看,即使在托管上下文中使用 delete 方法删除该实例在数据库对应数据,但如果该托管对象实例仍被代码或视图所引用,Swift 并不会销毁该实例,此时,托管对象上下文会将该实例 managedObjectContext..., formatter: itemFormatter)")因此在 ContentView ForEach ,item 并不会被视为一个可以引发视图更新 Source of truth ( 通过...在删除数据后,即使 item 内容发生了变化,也并不会引发该行声明语句( Text )刷新,从而不会出现强制解包失败情况。...为已删除托管对象实例提供正确备选内容一定会有人对本节题目感到奇怪,数据已经删除了,还需要提供什么信息?

3.3K20
  • SwiftUI 与 Core Data —— 数据获取

    SwiftUI 与 Core Data —— 问题[2]SwiftUI 与 Core Data —— 数据定义[3]访问我博客 www.fatbobman.com[4] 可以获得更好阅读体验以及最新更新内容...不可在 update 方法同步地改变引发视图更新数据与 SwiftUI 在视图中更新 Source of truth 逻辑一致,在一个视图更新周期中,不能对 Source of truth 再度更新...ID 顺序或数量没有发生变化时,即使数据属性值发生变化,MockableFetchRequest 也不会更新数据集。...,避免引发视图不必要更新通过创建一个具有包装用途引用类型来持有需要修改数据( 在 @State 持有引用 ),便可以达成如下目的:1、让数据生命周期与视图生存期一致;2、数据可更改;3、更改数据不会引发视图更新...这是由于一旦 SwiftUI 惰性容器中出现了多个 ForEach ,惰性容器将丧失对子视图优化能力。任何数据变动,惰性容器都将对所有的子视图进行更新而不是仅更新可见部分子视图。

    4.6K30

    使用 SwiftUI 创建一个灵活选择器

    Identifiable 和 Hashable 协议确保我们可以轻松创建具有 ForEach 循环 SwiftUI 视图。...如果满足条件,我们将当前项附加到 singleLineResult 更新可用 HStack 行宽,并继续到下一个元素。...singleLineResult 可能不会为空,也不会附加到 allLinesResult ——因为我们只在减去项目宽度结果小于 0 时附加 singleLineResult。...如我之前所提到,视图将使用嵌套 ForEach 循环创建。 需要记住是,ForEach 循环要求迭代集合每个元素必须符合 Identifiable 协议,或者应该具有唯一标识符。...这就是为什么我首先将整个 ForEach 循环包装在 HStack ,然后再包装在 Group ,以确保编译器可以正确解释一切。

    27920

    优化在 SwiftUI List 显示大数据集响应效率

    本文将通过一个优化列表视图案例,展现在 SwiftUI 查找问题、解决问题思路,其中也会对 SwiftUI 视图显式标识、@FetchRequest 动态设置、List 运作机制等内容有所涉及...标识( Identity )是 SwiftUI 在程序多次更新识别相同或不同元素手段,是 SwiftUI 理解你 app 关键。...在 SwiftUI 应用代码,绝大多数视图标识都是通过结构性标识 (有关结构性标识内容可以参阅 ViewBuilder 研究(下) —— 从模仿中学习[4])来实现 —— 通过视图层次结构(视图树...在 SwiftUI 为视图设置显式标识目前有两种方式: 在 ForEach 构造方法中指定 由于 ForEach 视图数量是动态且是在运行时生成,因此需要在 ForEach 构造方法中指定可用来标识子视图...但一旦为这些子视图添加了 id 修饰符,这些视图将无法享受到 List 提供优化能力 ( List 只会对 ForEach 内容进行优化)。

    9.1K20

    避免 SwiftUI 视图重复计算

    并且 SwiftUI 会在其变化时自动更新( 重新计算 )对应视图。 SwiftUI 上有一个困扰了不少人问题:为什么无法在视图构造函数,更改 State 包装变量值?...任何通过 objectWillChange.send 进行操作都将导致视图被刷新,无论实例属性内容是否被修改。...,ObservedObject 并不会SwiftUI 托管数据池中保存引用对象实例( @StateObject 会将实例保存在托管数据池中 ),仅会在属性图中创建视图与视图类型实例引用对象...例如:当 SwiftUI更新 ContentView 时,如果 SubView 构造参数( name 、age )内容发生了变化,SwiftUI 会对 SubView body 重新求值(...这是因为,我们将 Student 类型作为参数传递给了子视图,SwiftUI 在比对实例时候,并不会关心子视图中具体使用了 student 哪个属性,只要 student 发生了变化,那么就会重新计算

    9.2K81

    SwiftUI 动画机制

    极易产生不必要动画,这也是它被废弃主要原因。...appendWithAnimation 中使用了 withAnimation ,但由于 withAnimation闭包没有包含特定依赖项,因此并不会激活 SwiftUI 动画机制。...{ // 即使闭包中出现多个不同依赖项,也不会影响 animation 仅与指定依赖相关联特性 switch status{ case .one:...比如,在出场动画进行时,将状态 show 恢复成 true ,SwiftUI 将会保留当前分支状态(不会重新创建视图,参见本文附带范例)。...有关显性标识方面的内容可以参阅 优化在 SwiftUI List 显示大数据集响应效率[8] 一文 遗憾与展望 理论上,一旦你掌握了 SwiftUI 动画机制,就应该能轻松地驾驭代码,自由地控制动画

    14.7K40

    Ask Apple 2022 与 SwiftUI 有关问答(下)

    访问我博客 www.fatbobman.com[1] 可以获得更好阅读体验以及最新更新内容。....}// 可以用类似字典方式对元素进行操作,快速定位,同时在更新 IdentifiedArray 时,也不容易引发 ForEach 异常todos[id:id] = newTodo自定义布局Q:在实现自定义布局时...开发者即使无法实现这样布局容器,也应对各种尺寸需求定义有清晰理解。在 SwiftUI 布局 —— 尺寸( 上 )[8] 一文,对建议尺寸几种模式都进行了介绍。...这种 “软弃用” API 不会在代码自动补全中提供,而且通常处在文档单独一个部分。但编译器不会对现有的使用发出警告。...但这个滚动有两大问题,1、是一个未公开半成品,有可能会被从 SwiftUI 框架移除;2、不支持懒加载,即使和 Lazy 视图一起使用也会一次性加载全部视图。

    14.8K30

    SwiftU:在循环中创建视图

    SwiftUI为此提供了一个专用视图类型,称为ForEach。这可以在数组和范围上循环,根据需要创建尽可能多视图。更妙是,ForEach不会像我们手动输入视图一样被10个视图限制所影响。...ForEach在使用SwiftUIPicker视图时特别有用,它允许我们显示各种选项供用户选择。...为了证明这一点,我们将定义一个视图: 1、有一系列可能学生名字。 2、具有一个@State属性存储当前选定学生。...4、Picker与selectedStudent有双向绑定,这意味着它将开始显示0选择,但是在用户滑动选择器时更新属性。 5、在ForEach,我们从0数到(但不包括)数组学生数。...准备好后,将ContentView.swift放回最初创建项目时方式,这样我们就有了一个干净工作基础: import SwiftUI struct ContentView: View {

    2.2K20

    深入了解 SwiftUI 5 ScrollView 新功能

    SwiftUI 5.0 ,苹果大幅强化了 ScrollView 功能。新增了大量新颖、完善 API。本文将对这些新功能进行介绍,希望能够让它们更多、更早帮助到有需要开发者。...可以在 此处[1] 获取完整演示代码 访问我博客 www.fatbobman.com[2] 可以获得更好阅读体验以及最新更新内容。...当 scrollClipDisable 为 false 时,滚动内容会被裁剪以适应滚动容器边界。任何超出边界部分将不会显示。...当 scrollClipDisable 为 true 时,滚动内容不会被裁剪。它可以延伸超出滚动容器边界,从而显示更多内容。...应将此修饰符应用于 ScrollView 包含主要重复内容布局容器,如 LazyHStack 或 VStack。

    77720

    GeometryReader :好东西还是坏东西?

    这些批评并非全无道理,其中相当一部分已经通过新 API 在 SwiftUI 版本更新后得到了改善或解决。...官方文档“定义其内容( defines its content )”这一表述容易让人误以为 GeometryReader 主要功能是主动影响子视图,或者说其获取几何信息主要用于子视图,但实际上,...例如,如果我们想在 ScrollView 以 16:9 比例显示图片(即使图片自身比例与此不符): struct GeometryReaderInScrollView: View { var...(id: proxy.size.width) { width = proxy.size.width } 这样,即使数据发生变化,我们也能持续更新数据。...这既保证了信息获取准确性(尺寸、位置与要获取视图完全一致),也不会在视觉上造成额外影响。

    57470

    SwiftUI + Core Data App 内存占用优化之旅

    尽管 SwiftUI 惰性容器以及 Core Data 都有各自内存占用优化机制,但随着应用视图内容复杂( 图文混排 ),越来越多开发者遇到了内存占用巨大甚至由此导致 App 崩溃情况。...、惰性视图中子视图生命周期、托管对象惰值特性以及持久化存储协调器行缓存等内容有更多了解。...SwiftUI 惰性视图容器拥有对符合 DynamicViewContent 协议内容( 通过 ForEach 生成内容 )进行优化能力。...不过通过实验中分析,这些数据肯定是被缓存,且在被加载后,并不会因为返回惰值而自动从内存清除 因此,即使我们将托管对象返回成惰值状态,也仅能节省极少内存占用( 在本例几乎可以忽略不计 )。...即使我们在 onDisappear 中将该变量设置为 nil,但 SwiftUI 并没有释放之前它所占用空间。

    2.4K40

    SwiftUI + Core Data App 内存占用优化之旅

    尽管 SwiftUI 惰性容器以及 Core Data 都有各自内存占用优化机制,但随着应用视图内容复杂( 图文混排 ),越来越多开发者遇到了内存占用巨大甚至由此导致 App 崩溃情况。...、惰性视图中子视图生命周期、托管对象惰值特性以及持久化存储协调器行缓存等内容有更多了解。...SwiftUI 惰性视图容器拥有对符合 DynamicViewContent 协议内容( 通过 ForEach 生成内容 )进行优化能力。...不过通过实验中分析,这些数据肯定是被缓存,且在被加载后,并不会因为返回惰值而自动从内存清除 因此,即使我们将托管对象返回成惰值状态,也仅能节省极少内存占用( 在本例几乎可以忽略不计 )。...即使我们在 onDisappear 中将该变量设置为 nil,但 SwiftUI 并没有释放之前它所占用空间。

    1.3K10

    SwiftUI数据流之State&Binding

    SwiftUI,以单一数据源(single source of truth)为核心,构建了数据驱动状态更新机制。...@State检测是值类型 值类型仅有独立拥有者,而class类型可以多个指向一个;对于两个SwiftUI View而言,即使发送给他们两个相同struct对象,事实上他们每个View都得到了一份独立...类不需要mutating关键字,因为即使类实例被标记为常量,Swift仍然可以修改变量属性。 如果User是一个类,属性本身就不会改变,所以@State不会注意到任何东西,也无法重新加载视图。...即使类内某个属性值发生变化,但@State不监听这些,所以视图不会被重新加载。...,为了简化内容说明核心问题,只有两行内容,父视图是ProductsView,其中嵌套着子视图FilterView和列表元素,为了能够使得FilterView对showFavorited修改能够传递回父视图

    4K30

    AnyView 对 SwiftUI 性能影响

    你可以在这个出色 WWDC 演讲中找到有关 SwiftUI 差异机制更多细节。Apple 也多次提到,我们应该避免在 ForEach 中使用 AnyView,称其可能会导致性能问题。...此外,当你再次浏览列表时,性能不会改善(甚至变得更糟)。这是有道理,因为 SwiftUI 不知道它已经显示过此视图一次(因为它隐藏在 AnyView 下)。...在浏览数据时修改我们可以进行另一个测试是性能测试 - 向列表发送大量内容并强制更新视图(例如,响应消息),同时我们也浏览数据。这将在较短时间间隔内触发视图多次重绘。...为了更好地理解结果,我们需要深入了解 SwiftUI 工作原理。在这个关于 SwiftUI 性能 WWDC 会话,来自 SwiftUI 团队 Raj 讨论了列表或表需要提前知道所有标识符。...这也解释了为什么 AnyView 实现随着时间推移变慢 - 每次重绘时都需要从头开始创建更多内容。总结总而言之,在这些情景(包含异构视图可滚动列表),最好为容器不同视图使用具体类型。

    11700

    只在视图 Body 中生存变量

    SwiftUI 通过调用视图实例 body 属性来获取视图值。...不过就和通过 let _ = print("update") 能够帮助我们了解视图动态一样,掌握了在 body 通过 var 创建变量及应用方法,也将有助于开发者更好地理解 SwiftUI 视图求值逻辑并掌握其时机...在数据变化时(包括首次提取数据),FetchRequest 会根据数据量向视图发送更新信号(可通过 onRecevie 来验证) 虽然不能假设,但我们可以通过下面的方法,让 offset 数据,在首行获得重置...在 SwiftUI 所有的惰性容器,都会出现计算两次情况( 或许与惰性容器视图值保存机制有关 ),这就要求我们为了得到正确 offset 值必须进行除 2 操作。...即使不在 body 通过 var 来声明变量,我们同样可以通过使用一个引用类型实例来达成同样效果: 必须用 @State 来持有该实例,如此才能保证在视图存续期内,只有一个 holder struct

    68010

    架构之路 (五) —— VIPER架构模式(一)

    开始 首先看下主要内容: 在本教程,您将了解如何在SwiftUI和Combine中使用VIPER体系结构模式,同时构建一个允许用户创建公路旅行iOS应用程序,来自翻译。...VIPER为这种情况提供了一种替代方案,可以与SwiftUI和Combine结合使用,帮助构建具有清晰架构应用程序,该架构有效地分离了所需不同功能和职责,如用户界面、业务逻辑、数据存储和网络。...路由器Router处理屏幕之间导航。这与SwiftUI不同,在SwiftUI,视图显示任何新视图。...最后,在TripListView,在ForEach结束括号后面添加以下内容: .onDelete(perform: presenter.deleteTrip) 将. ondelete添加到SwiftUI...切换到TripListView.swift,将ForEach内容改为: self.presenter.linkBuilder(for: item) { TripListCell(trip: item

    17.4K10

    SwiftUI 布局协议 - Part2

    现在 SwiftUI 不会为我们插入位置。相反,它会插入角度值。我们布局代码将会完成剩下工作。 struct Wheel: Layout { // ......因此当我们使用上一部分描述"欺骗"技巧,我们必须使用 DispatchQueue 用队列更新。...这是可以实现,因为缓存是一个 inout 参数,我们可以在 placeSubviews 更新。...我发现更新路径会产生一个循环,即使该路径被绘制为不影响布局背景视图也是如此,所以为了避免这种循环,我们要确保路径发生改变,然后才更新绑定,这样就可以成功打破循环。...总结 即使你不打算写你自己布局容器,明白它是如何工作也会帮助你理解布局在 SwiftUI 一般工作方式。

    2.7K30

    解析 SwiftUI 两处由状态更新滞后引发严重 Bug

    原文发表在我博客 肘子Swift记事本视图变化在前、状态变化在后在 SwiftUI ,某些可编程控件在执行一定操作时,会先更新视图,待视图变化完成后再修改与其对应状态。...如果仅从上述两个例子考虑,无论状态调整是否及时,都不会出现什么错误结果。但是,当应用程序处于某些特殊状态或用户进行某些特定操作时,状态更新滞后会导致不可接受后果。...因此,当我们首先更新状态,然后 SwiftUI 再响应该状态变化(返回上层视图),即使此时对 AG 进行清理,仍将可以保证 AttributeGraph 完整性,应用自然不会出现问题。...状态更新滞后不仅存在于本文介绍两个案例,当开发者遇到类似情况时,可以尝试采用状态更新优先开发策略进行修改。总结今年 SwiftUI 已经进入了第五个年头。...随着版本提高,SwiftUI 功能也确实得到了相当程度增加。不过,即使在最新版本,在一些对 UIKit(AppKit)进行二次包装控件,仍有不少细节处理不到位问题。

    664110

    SwiftUI 视图生命周期研究

    它包含了 app 生命周期中可能会出现在屏幕上所有符合 View 协议类型(即使可能永远不会被渲染)。...除了必要参数设置外,不要做任何多余操作。这样即使 SwiftUI 创建了多余实例,也不会加大系统负担。 注册数据依赖 在 SwiftUI ,状态(或者说是数据)是驱动 UI 动力。...比如,在下面的几个场景,onAppear 和 onDisappear 都将违背大多数认知: •在 ZStack 即使视图不显示,也同样会触发 onAppear,即使消失(不显示),也不会触发 onDisappear...即使 Cell 视图没有显示在屏幕,仍会触发 onAppear ScrollView { VStack { ForEach(0..<100) { i in Text...开发者即使不了解文本上述内容,也可以让 SwiftUI 代码在日常中发挥出不错效率。但如果能够对视图生命周期有更深入了解,将可以帮助开发者在一些特定场合提高代码执行效率。

    4.4K30
    领券