SwiftUI:删除行时使用 Array/Index 的 ForEach 崩溃
Posted
技术标签:
【中文标题】SwiftUI:删除行时使用 Array/Index 的 ForEach 崩溃【英文标题】:SwiftUI: ForEach using Array/Index crashes when rows are deleted 【发布时间】:2019-12-14 13:58:33 【问题描述】:我已经看过几篇关于此的帖子,但到目前为止,似乎没有一个解决方案适合我。
我正在尝试使用 ForEach 创建一个可识别项目数组——其中包含 Text()
和 Toggle()
视图。该数组存储在@ObservableObject
的@Published
属性中。
我目前正在遍历索引以创建切换绑定(如other posts 中所建议的那样)。
一切似乎都在工作,直到我尝试删除一行。
(特别是最后一行 - 每次都会触发“致命错误:索引超出范围”。)
任何帮助将不胜感激!
struct Rule: Identifiable
let id: String
var displayName: String
var isEnabled: Bool
class UserData: ObservableObject
@Published var rules: [Rule] = []
struct RuleListView: View
@ObservableObject var userData: UserData
var body: some View
List
ForEach(userData.rules.indices, id: \.self) index in
HStack
Toggle(
isOn: self.$userData.rules[index].isEnabled
) Text("Enabled")
Text(self.userData.rules[index].displayName)
.onDelete(perform: delete)
func delete(at offsets: IndexSet)
userData.rules.remove(atOffsets: offsets)
【问题讨论】:
medium.com/better-programming/… 【参考方案1】:看来你的代码很复杂:
class UserData: ObservableObject
@Published var rules: [Rule] = []
当新元素添加到规则数组时会注意到,你可以通过声明来做到这一点:
@State var rules = [Rule]()
您可能想知道 Rule
类中的 isEnabled
何时更改。现在它没有发生。对于 ObservableObject
必须是 Rule
类。
记住这一点,如果您将代码更改为:
import SwiftUI
class Rule: ObservableObject, Identifiable
let id: String
var displayName: String
@Published var isEnabled: Bool
init(id: String, displayName: String, isEnabled: Bool)
self.id = id
self.displayName = displayName
self.isEnabled = isEnabled
struct ContentView: View
// for demonstration purpose, you may just declare an empty array here
@State var rules: [Rule] = [
Rule(id: "0", displayName: "a", isEnabled: true),
Rule(id: "1", displayName: "b", isEnabled: true),
Rule(id: "2", displayName: "c", isEnabled: true)
]
var body: some View
VStack
List
ForEach(rules) rule in
Row(rule: rule)
.onDelete(perform: delete)
func delete(at offsets: IndexSet)
rules.remove(atOffsets: offsets)
struct Row: View
@ObservedObject var rule: Rule
var body: some View
HStack
Toggle(isOn: self.$rule.isEnabled)
Text("Enabled")
Text(rule.displayName)
.foregroundColor(rule.isEnabled ? Color.green : Color.red)
新元素添加到规则数组时会通知,isEnabled
更改时也会通知。
这也解决了您的崩溃问题。
【讨论】:
以上是关于SwiftUI:删除行时使用 Array/Index 的 ForEach 崩溃的主要内容,如果未能解决你的问题,请参考以下文章
在 UIKit 中我们可以设置 label.numberOfLines = 0 当我们不知道文本将占用多少行时?在 SwiftUI 中有啥替代方法? [复制]