简体   繁体   中英

Model is hashable and Identifiable but still can't use ForEach

I've been at it for more than 8h refactoring the code over and over again and I can't get it to work, I have this in my view:

ForEach(allWalletsData.walletList) { walletKey in
    WalletStackView(user: user, walletAddress: walletKey)
}

and it complains saying: value of type 'String' has no member 'walletList' if I try another combination like:

ForEach(allWalletsData.walletList) { walletKey in
    WalletStackView(user: user, walletAddress: walletKey)
}

it says: referencing initializer 'init(_:content:)' on 'ForEach' requires that 'String' conform to 'Identifiable'

In my model I've wrote it 1000 different ways and still... doesn't work.

The information in it cannot be static, as I refresh the API, the data will change.

This is the model I've tried:

struct AllWalletsData: Decodable, Encodable {
    init(walletList: [String], walletsData: OrderedDictionary<String, WalletInformation>, combinedWalletTokensQuotesFormatted: String) {
        self.walletList = walletList
        self.walletsData = walletsData
        self.combinedWalletTokensQuotesFormatted = combinedWalletTokensQuotesFormatted
    }

    let walletList: [String]
    let walletsData: OrderedDictionary<String, WalletInformation>
    let combinedWalletTokensQuotesFormatted: String
}

extension AllWalletsData: Hashable, Identifiable {
    var id: [String] { walletList }

    func hash(into hasher: inout Hasher) {
        hasher.combine(combinedWalletTokensQuotesFormatted)
    }

    static func ==(lhs: AllWalletsData, rhs: AllWalletsData) -> Bool {
        if lhs.combinedWalletTokensQuotesFormatted != rhs.combinedWalletTokensQuotesFormatted {
            return false
        }
        return true
    }
}

I've burned out at this point trying to find out what's happening, does anyone know what's going on?

Instead of making AllWalletsData Identifiable , you need to make the individual items of your collection Identifiable or Hashable , or provide an ID.

Your collection is allWalletsData.walletList -- according to your model, this is of type [String] . So, one option is:

ForEach(allWalletsData.walletList, id: \.self) { walletKey in
    WalletStackView(user: user, walletAddress: walletKey)
}

That tells SwiftUI to use the String as the id for each item (which looks like what you were trying to accomplish by doing var id: [String] { walletList } .

Beware that if walletAddress doesn't contain truly unique elements, this (using id: \.self ) can lead to unpredictable results. The other route to go would be defining a model for your wallet that had truly unique ids (like a UUID ).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM