Created
January 21, 2021 16:15
-
-
Save khanlou/ae05d17d86fcdb2335c3decdef02e2ae to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// IndexedForEach.swift | |
// | |
// | |
// Created by Soroush Khanlou on 1/21/20. | |
// | |
// | |
import Foundation | |
import SwiftUI | |
/// A ForEach that also provides the index with each element. | |
/// With love from https://stackoverflow.com/a/61149111/946049 | |
struct IndexedForEach<Data: RandomAccessCollection, ID: Hashable, Content: View>: View { | |
var data: Data | |
var id: KeyPath<Data.Element, ID> | |
var content: (_ index: Data.Index, _ element: Data.Element) -> Content | |
var body: some View { | |
ForEach( | |
zip(self.data.indices, self.data).map { index, element in | |
return IndexInfo( | |
index: index, | |
id: self.id, | |
element: element | |
) | |
}, | |
id: \.elementID | |
) { indexInfo in | |
self.content(indexInfo.index, indexInfo.element) | |
} | |
} | |
init(_ data: Data, id: KeyPath<Data.Element, ID>, content: @escaping (_ index: Data.Index, _ element: Data.Element) -> Content) { | |
self.data = data | |
self.id = id | |
self.content = content | |
} | |
} | |
extension IndexedForEach where ID == Data.Element.ID, Content: View, Data.Element: Identifiable { | |
init(_ data: Data, @ViewBuilder content: @escaping (_ index: Data.Index, _ element: Data.Element) -> Content) { | |
self.init(data, id: \.id, content: content) | |
} | |
} | |
struct IndexInfo<Index, Element, ID: Hashable>: Hashable { | |
let index: Index | |
let id: KeyPath<Element, ID> | |
let element: Element | |
var elementID: ID { | |
self.element[keyPath: self.id] | |
} | |
init(index: Index, id: KeyPath<Element, ID>, element: Element) { | |
self.index = index | |
self.id = id | |
self.element = element | |
} | |
static func == (_ lhs: IndexInfo, _ rhs: IndexInfo) -> Bool { | |
lhs.elementID == rhs.elementID | |
} | |
func hash(into hasher: inout Hasher) { | |
self.elementID.hash(into: &hasher) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment