I'm trying to load a remote resource, so I'm using .onAppear to do that. However, when I use if/else inside the view, it causes the it to fire twice.
class FooVM: ObservableObject {
@Published var remoteText: String? = nil
func load() {
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
self.remoteText = "\(Date())"
}
}
}
struct Foo: View {
@StateObject private var vm = FooVM()
var body: some View {
content
.onAppear(perform: vm.load)
}
@ViewBuilder
private var content: some View {
if let text = vm.remoteText {
Text(text)
} else {
Circle()
}
}
}
struct ContentView: View {
var body: some View {
TabView {
Foo()
.tabItem {
Image(systemName: "circle.fill")
Text("Home")
}
}
}
}
EDIT: Turns out it only repro's when the content is inside a TabView. I updated the code above
Why is onAppear (and thus load) firing twice? Actually, in the Playground, it fires repeatedly every 2 seconds, but in a simulator in fires only twice.
How do I avoid it? Bear in mind that this is a simplified example.
Interestingly, if it wasn't a choice between Text and Circle, but just a different text within Text, then it would fire only once:
Text(vm.remoteText ?? "loading...")