[英]ForEach over an array of protocol implementations?
I'm starting to learn SwiftUI, and so I decided to write a simple password manager as a learning exercise.我开始学习 SwiftUI,所以我决定编写一个简单的密码管理器作为学习练习。 I've defined a
protocol
with the common attributes in my passwords:我在我的密码中定义了一个具有公共属性的
protocol
:
protocol Secret: Codable {
var id: String { get set }
var name: String { get set }
var createdDate: Date { get set }
var favorite: Bool { get set }
var category: SecretCategory { get set }
var notes: String { get set }
init(_ id: String, name: String)
init(_ id: String, name: String, favorite: Bool)
}
Then, I've defined a couple of Swift struct
s that implement this protocol
and define the properties of various types of secrets:然后,我定义了几个 Swift
struct
,它们实现了这个protocol
并定义了各种秘密的属性:
struct LoginSecret: Secret, Identifiable {
var id: String
var name: String
var createdDate: Date = Date()
var favorite: Bool = false
var category: SecretCategory = .login
var notes: String = ""
var username: String = ""
var encryptedPassword: String = ""
var websiteURLs: [String] = []
init(_ id: String, name: String) {
self.id = id
self.name = name
}
init(_ id: String, name: String, favorite: Bool) {
self.id = id
self.name = name
self.favorite = favorite
}
}
...and... ...和...
struct BankAccountSecret: Secret, Identifiable {
var id: String
var name: String
var createdDate: Date = Date()
var favorite: Bool = false
var category: SecretCategory = .bankAccounts
var notes: String = ""
var bankName: String = ""
var nameOnAccount: String = ""
var routingNumber: String = ""
var accountNumber: String = ""
var swift: String = ""
var iban: String = ""
var encryptedPIN: String = ""
var branchPhoneNumber: String = ""
var branchAddress: Address = Address()
init(_ id: String, name: String) {
self.id = id
self.name = name
}
init(_ id: String, name: String, favorite: Bool) {
self.id = id
self.name = name
self.favorite = favorite
}
}
These work just fine, and I'm able to Encode/Decode values in JSON for display later.这些工作正常,我可以对 JSON 中的值进行编码/解码,以便稍后显示。 However, now I'm working on my SwiftUI code.
但是,现在我正在处理我的 SwiftUI 代码。 I want to display each item in a
List
, iterating over an Array
of Secret
objects using SwiftUI's ForEach
.我想在
List
中显示每个项目,使用 SwiftUI 的ForEach
遍历Secret
对象Array
。 My code looks like this:我的代码如下所示:
struct SecretsListView: View {
@State
var secrets: [Secret]
var body: some View {
NavigationView {
List {
ForEach(secrets) { secret in
<snip>
}
}
}
}
}
However, when I compile I get an error saying...但是,当我编译时,我收到一条错误消息...
Value of protocol type 'Secret' cannot conform to 'Identifiable'; only struct/enum/class types can conform to protocols
Is there no way to iterate over an array of Secret
objects?有没有办法遍历
Secret
对象数组? Is there a different way to accomplish this?有没有不同的方法来实现这一点? Is this issue specific to SwiftUI's
ForEach
?这个问题是 SwiftUI 的
ForEach
特有的吗? Should I use the standard Swift Array
forEach
method instead?我应该改用标准的 Swift
Array
forEach
方法吗? Any guidance you can provide is greatly appreciated.非常感谢您提供的任何指导。 I've worked with Swift and UIKit for a while, but SwiftUI is new and I want to make sure I'm developing for the framework correctly.
我已经使用 Swift 和 UIKit 有一段时间了,但是 SwiftUI 是新的,我想确保我正在为框架正确开发。
Yes, only SwiftUI.ForEach
requires the Identifiable
conformance, Array.forEach
does not require it.是的,只有
SwiftUI.ForEach
需要Identifiable
一致性, Array.forEach
不需要它。
There are several other initialisers of ForEach
though that don't require your model type to conform to Identifiable
. ForEach
的其他几个初始化程序虽然不需要您的 model 类型符合Identifiable
。
You could use init(_ data: Data, id: KeyPath<Data.Element, ID>, content: @escaping (Data.Element) -> Content)
for instance (assuming that ID
conforms to Hashable
, which Secret.id
does, since it's a String
).例如,您可以使用
init(_ data: Data, id: KeyPath<Data.Element, ID>, content: @escaping (Data.Element) -> Content)
(假设ID
符合Hashable
, Secret.id
确实如此,因为它是一个String
)。
ForEach(secrets, id: \.id) { secret in
<snip>
}
Another solution would be passing the indices of the array to ForEach
, then you could use ForEach(secrets.indices)
, but since you have a Hashable
property on Secret
that you can use as the id
, that's a the previous one is a better solution.另一种解决方案是将数组的索引传递给
ForEach
,然后您可以使用ForEach(secrets.indices)
,但是由于您在Secret
上有一个可用作id
的Hashable
属性,因此前一个是更好的解决方案.
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.