首页 > 解决方案 > ForEach 在一系列协议实现上?

问题描述

我开始学习 SwiftUI,所以我决定编写一个简单的密码管理器作为学习练习。我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)

}

然后,我定义了几个 Swiftstruct来实现它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
    }
}

...和...

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
    }
}

这些工作正常,我可以在 JSON 中编码/解码值以便稍后显示。但是,现在我正在编写我的 SwiftUI 代码。我想在一个中显示每个项目,使用SwiftUIList对一个对象进行迭代。我的代码如下所示:ArraySecretForEach

struct SecretsListView: View {

    @State    
    var secrets: [Secret]
    
    var body: some View {
        NavigationView {
            List {
               ForEach(secrets) { secret in
                  <snip>
               }
            }
        }
   }
}

但是,当我编译时,我收到一条错误消息...

Value of protocol type 'Secret' cannot conform to 'Identifiable'; only struct/enum/class types can conform to protocols

有没有办法遍历Secret对象数组?有没有不同的方法来实现这一点?这个问题是 SwiftUI 特有的ForEach吗?我应该改用标准的 SwiftArray forEach方法吗?非常感谢您提供的任何指导。我使用 Swift 和 UIKit 已经有一段时间了,但是 SwiftUI 是新的,我想确保我正在为框架进行正确的开发。

标签: swiftforeachswiftui

解决方案


是的,只SwiftUI.ForEach需要Identifiable一致性,Array.forEach不需要它。

虽然还有其他几个初始化器ForEach不需要您的模型类型符合Identifiable.

例如,您可以使用init(_ data: Data, id: KeyPath<Data.Element, ID>, content: @escaping (Data.Element) -> Content)(假设ID符合HashableSecret.id确实如此,因为它是 a String)。

ForEach(secrets, id: \.id) { secret in
    <snip>
}

另一种解决方案是将数组的索引传递给ForEach,然后您可以使用ForEach(secrets.indices),但是由于您有一个可以用作的Hashable属性,因此前一个是更好的解决方案。Secretid


推荐阅读