Skip to content

Commit 30ec782

Browse files
committed
Init
0 parents  commit 30ec782

File tree

3 files changed

+192
-0
lines changed

3 files changed

+192
-0
lines changed

.gitignore

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
# Created by https://www.toptal.com/developers/gitignore/api/swift
2+
# Edit at https://www.toptal.com/developers/gitignore?templates=swift
3+
4+
### Swift ###
5+
# Xcode
6+
#
7+
# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
8+
9+
## User settings
10+
xcuserdata/
11+
12+
## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9)
13+
*.xcscmblueprint
14+
*.xccheckout
15+
16+
## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4)
17+
build/
18+
DerivedData/
19+
*.moved-aside
20+
*.pbxuser
21+
!default.pbxuser
22+
*.mode1v3
23+
!default.mode1v3
24+
*.mode2v3
25+
!default.mode2v3
26+
*.perspectivev3
27+
!default.perspectivev3
28+
29+
## Obj-C/Swift specific
30+
*.hmap
31+
32+
## App packaging
33+
*.ipa
34+
*.dSYM.zip
35+
*.dSYM
36+
37+
## Playgrounds
38+
timeline.xctimeline
39+
playground.xcworkspace
40+
41+
# Swift Package Manager
42+
# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
43+
# Packages/
44+
# Package.pins
45+
# Package.resolved
46+
# *.xcodeproj
47+
# Xcode automatically generates this directory with a .xcworkspacedata file and xcuserdata
48+
# hence it is not needed unless you have added a package configuration file to your project
49+
# .swiftpm
50+
51+
.build/
52+
53+
# CocoaPods
54+
# We recommend against adding the Pods directory to your .gitignore. However
55+
# you should judge for yourself, the pros and cons are mentioned at:
56+
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
57+
# Pods/
58+
# Add this line if you want to avoid checking in source code from the Xcode workspace
59+
# *.xcworkspace
60+
61+
# Carthage
62+
# Add this line if you want to avoid checking in source code from Carthage dependencies.
63+
# Carthage/Checkouts
64+
65+
Carthage/Build/
66+
67+
# Accio dependency management
68+
Dependencies/
69+
.accio/
70+
71+
# fastlane
72+
# It is recommended to not store the screenshots in the git repo.
73+
# Instead, use fastlane to re-generate the screenshots whenever they are needed.
74+
# For more information about the recommended setup visit:
75+
# https://docs.fastlane.tools/best-practices/source-control/#source-control
76+
77+
fastlane/report.xml
78+
fastlane/Preview.html
79+
fastlane/screenshots/**/*.png
80+
fastlane/test_output
81+
82+
# Code Injection
83+
# After new code Injection tools there's a generated folder /iOSInjectionProject
84+
# https://github.com/johnno1962/injectionforxcode
85+
86+
iOSInjectionProject/
87+
88+
.DS_Store
89+
90+
.swiftpm
91+
# End of https://www.toptal.com/developers/gitignore/api/swift

Package.swift

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// swift-tools-version: 6.0
2+
// The swift-tools-version declares the minimum version of Swift required to build this package.
3+
4+
import PackageDescription
5+
6+
let package = Package(
7+
name: "swiftui-indexed-for-each",
8+
platforms: [.iOS(.v13), .macOS(.v10_15), .watchOS(.v6), .tvOS(.v13)],
9+
products: [
10+
// Products define the executables and libraries a package produces, making them visible to other packages.
11+
.library(
12+
name: "swiftui-indexed-for-each",
13+
targets: ["swiftui-indexed-for-each"]),
14+
],
15+
targets: [
16+
// Targets are the basic building blocks of a package, defining a module or a test suite.
17+
// Targets can depend on other targets in this package and products from dependencies.
18+
.target(
19+
name: "swiftui-indexed-for-each"),
20+
21+
]
22+
)
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import SwiftUI
2+
3+
public struct IndexedForEach<Element, Content>: View where Content: View {
4+
5+
let data: Array<Element>
6+
7+
let content: (Array<Element>.Index, Element) -> Content
8+
9+
public init(data: Array<Element>, @ViewBuilder content: @escaping (Array<Element>.Index, Element) -> Content) {
10+
self.data = data
11+
self.content = content
12+
}
13+
14+
public var body: some View {
15+
ForEach(IndexedArray.init(base: data), id: \.0) { e in
16+
content(e.0, e.1)
17+
}
18+
}
19+
20+
}
21+
22+
struct IndexedArray<SourceElement>: RandomAccessCollection {
23+
24+
typealias Iterator = IndexingIterator<Self>
25+
26+
typealias Element = (Index, Array<SourceElement>.Element)
27+
28+
typealias Index = Array<SourceElement>.Index
29+
30+
typealias SubSequence = ArraySlice<Element>
31+
32+
typealias Indices = Array<SourceElement>.Indices
33+
34+
var base: [SourceElement]
35+
36+
var indices: Array<SourceElement>.Indices { base.indices }
37+
38+
var startIndex: Array<SourceElement>.Index { base.startIndex }
39+
40+
var endIndex: Array<SourceElement>.Index { base.endIndex }
41+
42+
init(base: consuming [SourceElement]) {
43+
self.base = base
44+
}
45+
46+
func index(before i: Index) -> Index {
47+
base.index(before: i)
48+
}
49+
50+
func index(after i: Index) -> Index {
51+
base.index(after: i)
52+
}
53+
54+
subscript(bounds: Range<Index>) -> SubSequence {
55+
56+
// TODO: This is not efficient
57+
58+
var slice: [Element] = []
59+
60+
for index in bounds {
61+
slice.append((index, base[index]))
62+
}
63+
64+
return .init(slice)
65+
}
66+
67+
subscript(position: Index) -> Element {
68+
return (position, base[position])
69+
}
70+
71+
}
72+
73+
#Preview {
74+
VStack {
75+
IndexedForEach(data: [1, 2, 3]) { index, element in
76+
Text("\(index): \(element)")
77+
}
78+
}
79+
}

0 commit comments

Comments
 (0)