SwiftUI Initialzier requires String conform to Identifiable

Viewed 11829

I am attempting writing some SwiftUI code for the very first time and am running into an issue while trying to make a simple table view. In this code teams is an array of String, but the List is giving me the following error: Initializer 'init(_:rowContent:)' requires that 'String' conform to 'Identifiable'

var body: some View {
        let teams = getTeams()
        Text("Hello there")
        List(teams) { team in
            
        }
        
    }

Anyone have an idea what it means?

4 Answers

The argument of List is required to be unique, that's the purpose of the Identifiable protocol

You can do

List(teams, id: \.self) { team in

but then you are responsible to ensure that the strings are unique. If not you will get unexpected behavior.

Better is to use a custom struct with an unique id conforming to Identifiable

I'm assuming that getTeams() returns a [String] (a.k.a. an Array<String>).

The issue, as the error suggests, are the strings aren't identifiable. But not just in the "they don't conform to the Identifiable protocol" sense, but in the broader sense: if two strings are "foo", one is indistinguishable from the other; they're identical.

This is unacceptable for a List view. Imagine you had a list that contains "foo" entries, and the users dragged to rearrange one of them. How would List be able to tell them apart, to know which of the two should move?

To get around this, you need to use an alternate source of identity to allow the List to distinguish all of its entries.

You should watch the "Demystify SwiftUI" talk from this year's WWDC. It goes into lots of detail on exactly this topic.

If your trying to go over a 'List' of items of type 'Struct' Change the Struct to use 'Identifiable':

my Struct:

 struct Post : Identifiable{
    let id = UUID()
    let title: String
}

my List :

let posts = [
    Post( title: "hellow"),
    Post( title: "I am"),
    Post( title: "doing"),
    Post( title: "nothing")
]

then you can go over your List:

List(posts){post in
   Text(post.title
}
Related