Reputation: 172
Given the following code:
import SwiftUI
struct ContentView: View {
var body: some View {
NavigationView {
VStack {
ForEach(0..<3) { index in
NavigationLink(destination: TestView(index)) {
Text("Hello, world!")
}
}
}
}
}
}
struct TestView: View {
let id = UUID()
init(_ index: Int) {
print("\(id) \(index)")
}
var body: some View {
Text("Hello world!")
}
}
I would expect three lines to be printed to the console, but there are six, two for each index. Every id of the TestView is different.
Is this expected behavior?
UPDATE: Using NavigationStack, every index gets printed four times!
EDIT:
struct ContentView: View {
static var indices = Set<Int>()
var body: some View {
NavigationView {
VStack {
ForEach(0..<3) { index in
NavigationLink(destination: generateTestView(index) as? TestView) {
Text("Hello, world!")
}
}
}
}
}
func generateTestView(_ index: Int) -> any View {
if !Self.indices.contains(index) {
Self.indices.insert(index)
return EmptyView()
}
return TestView(index)
}
}
The links lead to the TestView instead of the EmptyView, indicating that the View created last is the one we actually use.
Upvotes: 0
Views: 78
Reputation: 10422
It could be. Although we think of the View
objects in our code as visual elements on screen, they're really descriptions of how those elements fit into the graph of objects that SwiftUI's rendering system needs to know about.
SwiftUI walks through that graph regularly to see what's changed and what needs to be rendered. Instances of your View
structs will get created and destroyed as it does so, even if nothing changes on screen.
So I'd advise not to get too hung up on how many times a View
gets created. Instead, accept that it'll happen more often than you think, and as a result limit init()
to setting internal state based on what's passed in. Creating a new UUID in init
is what could be considered a "side-effect", and is the sort of thing you shouldn't do in init
.
If you needed a unique UUID for each subview, that ought to be part of the data you pass in to the view.
Upvotes: 1