如何在 Swift 中确认对 Identifiable 协议的枚举?

How to confirm an enumeration to Identifiable protocol in Swift?

我正在尝试使用新 SwiftUI 框架的枚举中的案例原始值制作一个列表。但是,我在使 'Data' 符合 Identifiable 协议时遇到了麻烦,而且我真的找不到如何做到这一点的信息。它告诉我 "Initializer 'init(_:rowContent:)' requires that 'Data' conform to 'Identifiable'" 存根在最后一个扩展中为我提供了一个 ObjectIdentifier 变量,但不知道我应该 return。你能告诉我怎么做吗?如何使数据符合可识别,以便我可以使用原始值制作列表?

enum Data: String {
    case firstCase = "First string"
    case secondCase = "Second string"
    case thirdCase = "Third string"
}

extension Data: CaseIterable {
    static let randomSet = [Data.firstCase, Data.secondCase]
}

extension Data: Identifiable {
    var id: ObjectIdentifier {
        return //what?
    }

}

//-------------------------ContentView------------------------
import SwiftUI

struct Lala: View {
    var name: String

    var body: some View {
        Text(name)
    }
}

struct ContentView: View {
    var body: some View {
        return List(Data.allCases) { i in
            Lala(name: i.rawValue)
        }
    }
}

⚠️ 尽量不要为您的内部模块使用 Data 等已使用的名称。我将在这个答案中使用 MyEnum 代替


当某些东西符合 Identifiable 时,它必须 return 可以被识别的东西。所以你应该 return 一些独特的东西。对于 String base enumrawValue 是您的最佳选择:

extension MyEnum: Identifiable {
    var id: RawValue { rawValue }
}

另外,enum通常可以自己识别:

extension MyEnum: Identifiable {
    var id: Self { self }
}

⚠️ 注意 1:如果你 return 不稳定的东西,比如 UUID()index,这意味着每次获得 object 时都会得到一个新的 object,这将破坏可重用性,并可能导致史诗般的内存和布局进程使用,以及视图管理问题(如转换)管理等

看看这个添加新宠物的奇怪动画:

注释 2:从 Swift 5.1 开始,single-line 闭包不需要 return 关键字。

注意 3:尽量不要为您自己的类型使用 Data 这样的全球知名名称。至少使用命名空间,比如 MyCustomNameSpace.Data


内联模式

您可以通过其中一个元素的键路径使任何集合可迭代内联

例如self:

List(MyEnum.allCases, id:\.self)

或任何其他兼容的键路径:

List(MyEnum.allCases, id:\.rawValue)

✅ 标识符清单:(来自WWDC21)

  • 谨慎使用随机标识符。
  • 使用稳定的标识符。
  • 保证唯一性,一标一码

你可以这样试试:

enum MyEnum: Identifiable {
    case valu1, valu2
    
    var id: Int {
        get {
            hashValue
        }
    }
}

另一种使用关联值的方法是做这样的事情,其中​​所有关联值都是可识别的。

enum DataEntryType: Identifiable {
    var id: String {
        switch self {
        case .thing1ThatIsIdentifiable(let thing1):
            return thing1.id
        case .thing2ThatIsIdentifiable(let thing2):
            return thing2.id
        }
    }
    
    case thing1ThatIsIdentifiable(AnIdentifiableObject)
    case thing2ThatIsIdentifiable(AnotherIdentifiableObject)

版权所有 © 2021 Mark Moeykens。版权所有。 | @BigMtnStudio Combine Mastery in SwiftUI 书

enum InvalidAgeError: String, Error , Identifiable {
    var id: String { rawValue }
    case lessThanZero = "Cannot be less than zero"
    case moreThanOneHundred = "Cannot be more than 100"
}