我正在尝试做一个最喜欢的报纸列表。在编辑模式下,列表显示所有可用的报纸,用户可以从中选择他的最爱。选择最爱后,列表只显示最爱。下面是我的代码:
struct Newspaper: Hashable {
let name: String
}
struct ContentView: View {
@State var editMode: EditMode = .inactive
@State private var selection = Set<Newspaper>()
var favorites: [Newspaper] {
selection.sorted(by: ({ $0.name < $1.name }))
}
let newspapers = [
Newspaper(name: "New York Times"),
Newspaper(name: "Washington Post")
]
var body: some View {
NavigationView {
List(editMode == .inactive ? favorites : newspapers, id: \.name, selection: $selection) { aliasItem in
Text(aliasItem.name)
}
.toolbar {
EditButton()
}
.environment(\.editMode, self.$editMode)
}
}
}
问题是列表进入编辑模式,但是选择小部件没有出现。如果我用String
数组替换Newspaper
(并相应地修改其余代码),那么选择小部件确实出现了,并且列表按预期工作。有人能解释一下问题是什么吗?
我最初尝试使用Identifiable
报纸,如下所示:
struct Newspaper: Codable, Identifiable, Equatable, Hashable {
var id: String { alias + publicationName }
let alias: String
let publicationName: String
}
由于这不起作用,我测试了上面的简单版本,试图找出问题所在。
因为我需要保存收藏夹,所以Newspapers必须是Codable,因此不能使用UUID,因为它们是从磁盘读取的,而完整的Newspapers数组是从服务器获取的,这就是为什么我将id
作为计算属性。
Yrb:s的回答提供了问题的解决方案:选择集的类型必须与Identifiable
结构体中使用的id
类型相同,而不是List
中显示的类型。
因此,在我的例子中(使用Identifiable
Newspaper版本),选择集必须是Set<String>
类型,而不是Set<Newspaper>
类型,因为Newspaper的id
是String
。
2条答案
按热度按时间eeq64g8w1#
您的问题源于
List's
选择模式使用id:
属性来跟踪您的选择。由于您将List
声明为List(..., id: \.name, ...)
,因此selection
变量的类型需要为String
。如果将其更改为List(..., id: \.self, ...)
,它将正常工作。但是在这样的列表中使用self会带来它自己的问题。为了保持最佳实践,暂时忘记选择,您应该使用Identifiable
结构。List
应该通过结构上的id
参数来标识元素。(我使用了UUID)对于选择,这意味着您需要将其定义为
@State private var selection = Set<UUID>()
。这就留下了处理favorites
计算变量的工作。您只需过滤newspapers
数组以查找包含在selection
中的元素,而不是返回selection
的数组。最后,这就留下了以下内容:编辑:
在您的评论中,您说
Newspaper
需要"可编码",并暗示服务器响应中没有id
参数。下面的Newspaper
是Codable
,但不希望服务器响应中有id
,而是简单地加上它自己的常量id
。计算id
是一个非常糟糕的主意。id
应该永远不会改变,并且应该是唯一的。UUID
可以提供这些。sdnqo3pr2#
您可以将结构体用于List的选择,但必须告知SwiftUI这一点,因此它不使用结构体的ID。原始代码使用添加的适当标记,特别是: