首页 > 解决方案 > SwiftUI 的 ForEach 是否会缓存子视图的 @State 变量超出其存在范围?

问题描述

所以这里有一小段代码总结了一个我无法弄清楚atm的问题。

在下面的代码中,我向由 Enum 键入的字典添加和删除条目。

我期望的是,每次我添加一个项目时,都会在元素视图中生成一个新的随机数并显示出来。

发生的情况是,对于每个相同的 Ident,都会出现相同的随机数 - 尽管 ForEach 循环具有该 Ident 键不再在字典中的状态,但事件。似乎 ForEach 不会清除不再存在的元素视图的 @State 变量,而是在向字典中添加具有相同标识的新条目时重用它们。

这是预期的行为吗?我究竟做错了什么?

这是代码:

import Foundation
import SwiftUI


enum Ident:Int, Comparable, CaseIterable {
    case one=1, two, three, four
    
    static func < (lhs: Ident, rhs: Ident) -> Bool {
        lhs.rawValue < rhs.rawValue
    }
    
}

extension Dictionary where Key == Ident,Value== String {
    
    var asSortedArray:Array<(Ident,Value)> {
        Array(self).sorted(by: { $0.key < $1.key })
    }
    
    var nextKey:Ident? {
        if self.isEmpty {
            return .one
        }
        else {
            return Array(Set(Ident.allCases).subtracting(Set(self.keys))).sorted().first
        }
    }
}


struct ContentView: View {
    @State var dictionary:[Ident:String] = [:]
    
    var body: some View {
        Form {
            Section {
                ForEach(dictionary.asSortedArray, id: \.0) { (ident, text) in
                    Element(dictionary: $dictionary, ident: ident, text: text)
                }
            }
            Section {
                Button(action: {
                    if let nextIdent = dictionary.nextKey {
                        dictionary[nextIdent] = "Something"
                    }
                }, label: {
                    Text("Add one")
                })
            }
        }
    }
}

struct Element:View {
    @Binding var dictionary:[Ident:String]
    var ident:Ident
    var text:String
    @State var random:Int = Int.random(in: 0...1000)
    
    var body: some View {
        HStack {
            Text(String(ident.rawValue))
            Text(String(random))
            Button(action: {
                dictionary.removeValue(forKey: ident)
            }, label: {
                Text("Delete me.")
            })
            Spacer()
        }
    }
}

标签: swiftui

解决方案


推荐阅读