Как получить индекс строки в списке SwiftUI?

Я хотел бы иметь нумерованный список, в котором каждая строка имеет номер.

Что-то вроде этого

но я не вижу подходящего API для этого в List инициализаторах

На данный момент я вижу обходной путь

var persons = ["Boris", "Anna", "Tom"]

// MARK: - Body
func body(props: Props) -> some View {
    List(persons.indices, id: \.self) { index in
        Text("\(index) \(self.persons[index])")
    }
}

person Tikhonov Alexander    schedule 08.09.2019    source источник


Ответы (3)


Использование .indices () не является обходным путем, это правильный способ сделать это.

В качестве альтернативы вы также можете использовать код в примечаниях к выпуску для массива indexed ():

struct ContentView: View {
    var persons = ["Boris", "Anna", "Tom"]

    var body: some View {
        VStack {
            List(persons.indexed(), id: \.1.self) { idx, person in
                Text("\(idx) - \(person)")
            }
        }
    }
}


// This is taken from the Release Notes, with a typo correction, marked below
struct IndexedCollection<Base: RandomAccessCollection>: RandomAccessCollection {
    typealias Index = Base.Index
    typealias Element = (index: Index, element: Base.Element)

    let base: Base

    var startIndex: Index { base.startIndex }

   // corrected typo: base.endIndex, instead of base.startIndex
    var endIndex: Index { base.endIndex }

    func index(after i: Index) -> Index {
        base.index(after: i)
    }

    func index(before i: Index) -> Index {
        base.index(before: i)
    }

    func index(_ i: Index, offsetBy distance: Int) -> Index {
        base.index(i, offsetBy: distance)
    }

    subscript(position: Index) -> Element {
        (index: position, element: base[position])
    }
}

extension RandomAccessCollection {
    func indexed() -> IndexedCollection<Self> {
        IndexedCollection(base: self)
    }
}
person kontiki    schedule 08.09.2019
comment
Я пробовал, но у меня ничего не вышло, сборка не удалась, и никаких ошибок не было ... - person Najam; 24.01.2020
comment
@kontiki, да, это работает, но я получил сообщение об ошибке. Тип «_» не имеет элемента «1», когда я добавляю условие if в List / ForEach. - person foolbear; 16.02.2020

Вы можете просто использовать enumerated, например https://github.com/onmyway133/blog/issues/515

struct CountriesView: View {
    let countries: [Country]

    var body: some View {
        let withIndex = countries.enumerated().map({ $0 })

        return List(withIndex, id: \.element.name) { index, country in
            NavigationLink(
                destination: CountryView(country: country),
                label: {
                    VStack(alignment: .leading) {
                        Text(country.name)
                            .styleMultiline()
                    }
                    .paddingVertically()
                }
            )
        }
    }
}
person onmyway133    schedule 22.11.2019

Это пример Apple:

var landmarkIndex: Int {
userData.landmarks.firstIndex(where: { $0.id == landmark.id })!}

Для тебя:

var persons = ["Boris", "Anna", "Tom"]

// MARK: - Body

func body(props: Props) -> some View {
List(persons.indices, id: \.self) { index in

var i: Int {
persons.firstIndex(where: { $0.id == index.id })!}

    Text("\(i) \(self.persons[i])")
}}
person user13082173    schedule 18.03.2020