For loop in SwiftUI using ForEach
source link: https://sarunw.com/posts/swiftui-foreach/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
You can easily support sarunw.com by checking out this sponsor.
Sponsor sarunw.com and reach thousands of iOS developers.
How to create views using For loop in SwiftUI
When creating an app, there is a time when you want to create a repetitive view or a collection of views from an array of data. We can do that in SwiftUI with ForEach
.
ForEach
can create views on demand from an underlying collection of identified data.
Identified data that work with ForEach
can be classified into three groups.
Create views from a range of integer
The first initializer allows us to create views from a range of integers.
Here is the example using ForEach
to loop over a range of 1..<11
, then we create a text view from an integer within that range.
struct ContentView: View {
var body: some View {
VStack {
ForEach(1..<11) { index in
Text("Item \(index)")
}
}
}
}
Create ten text views using a range.
ClosedRange
won't work with ForEach
, e.g., 1...10
.
If you try using a ClosedRange
, you will get the following error.
Cannot convert value of type 'ClosedRange<Int>' to expected argument type 'Range<Int>'
struct ContentView: View {
var body: some View {
VStack {
// Cannot convert value of type 'ClosedRange<Int>' to expected argument type 'Range<Int>'
ForEach(1...10) { index in
Text("Item \(index)")
}
}
}
}
Create views from an Identifiable data
Identifiable
is a protocol that ask for one thing, a stable identity to a class or value type.
Identity can range from a database id, a book's ISBN, or a user's identity number.
The only thing you need to do is to make your data conform to the Identifiable
protocol.
Identifiable
protocol required two things.
- An variable name
id
of typeID
. ID
must be hashable (Conform toHashable
protocol).
public protocol Identifiable {
/// A type representing the stable identity of the entity associated with
/// an instance.
associatedtype ID : Hashable
/// The stable identity of the entity associated with this instance.
var id: Self.ID { get }
}
If your data has a property that you can uniquely identify the data, e.g., id
, ISBN
, or SKU
, you can make your data conform to the Identifiable
protocol. Then use a collection of that data in a ForEach
.
Here is a Book
model where we use an ISBN as an id
.
struct Book: Identifiable {
var id: String {
return isbn
}
let isbn: String
let name: String
}
And here is an example where we use a collection of Book
in a ForEach
.
struct ContentView: View {
let books = [
Book(isbn: "0135264022", name: "iOS Programming: The Big Nerd Ranch Guide"),
Book(isbn: "0439708184", name: "Harry Potter and the Sorcerer's Stone"),
Book(isbn: "0358439191", name: "The Lord of the Rings 3-Book Paperback Box Set")
]
var body: some View {
List {
ForEach(books) { book in
Text(book.name)
}
}
}
}
ForEach with identifiable data.
You can easily support sarunw.com by checking out this sponsor.
Sponsor sarunw.com and reach thousands of iOS developers.
Create views from any data with a keypath to the data's identity
If you have a primitive or simple data that you don't want to conform to the Identifiable
protocol, ForEach
has an option for you to explicitly provide a key path to property that can uniquely identify that data.
In the following example, we have an array of color names that we want users to pick from. A simple string is sufficient for the picker, and I don't want to bother creating a new type for it. So, I use the \.self
keypath, which references to string itself as an identity.
struct ContentView: View {
var colors = ["Red", "Green", "Blue"]
@State private var selectedColor = "Red"
var body: some View {
VStack {
Picker("Please select a color", selection: $selectedColor) {
// 1
ForEach(colors, id: \.self) {
Text($0)
}
}
.pickerStyle(.wheel)
Text("You selected: \(selectedColor)")
}
}
}
1 We provide a self key path \.self
as an id
.
ForEach with keypath.
\.self
is a special path that can refer to an instance instead of a property, which is a string in this case.
You can read more about the key path in Swift KeyPath.
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK