NavigationLink destination gets called before choosing it

Hi,

Because the xcode simulator does not work with bluetooth I noticed that a destination view @State variable gets called before clicking:

In this settings view there a section for Bluetooth.

struct SettingsView: View {
    @State private var viewModel = SettingsViewModel()
    
    var body: some View {
        NavigationStack {
            List {
                //
                //
                //
               Section("Bluetooth Low Energy") {
                    NavigationLink (destination: BleModulesView()) {
                        HStack {
                            Image(systemName: "iphone.gen2.radiowaves.left.and.right")
                                .symbolRenderingMode(.palette)
                                .foregroundStyle(.primary, .teal)
                                .font(.system(size:30))
                            Text("Read and/or change parameters when module is nearby")
                                .frame(maxWidth: .infinity ,alignment: .leading)
                                .padding(4)
                        }
                    }
                    .font(.subheadline)
                }
                .headerProminence(.increased)
                //
                //

...

When I click on that item, it opens a new view (the destination):

import SwiftUI

struct BleModulesView: View {
    @State private var bluetoothScanner = BluetoothScanner()
    
    var body: some View {

It all works fine, BUT:

I noticed, via the errors in the simulator, that as soon as I open the SettingsView the BluetoothScanner from BleModulesView gets called?
Why?
Why does it gets called before being clicked (and displayed)?

Korstiaan

This forum is for the Swift language, not for frameworks written in Swift like SwiftUI or other private Apple frameworks. You're more likely to get helpful responses if you ask somewhere like stackoverflow or the Apple Developer forums.

That said the reason for the behavior you're seeing is that when you create the NavigationLink an instance of BLEModulesView is being created, including all of it's properties.

Depending on how NavigationView (or any view that takes a closure that returns a View) is implemented it can run the closure in the initializer, when it's body is called, or whenever it wants to. That means you can't assume that your View is/will be on screen when it's created, and should use functionality like .onAppear to handle your Views being shown.

Hi Isaac,

I'm sorry, I didn't knew I could not ask SwiftUI questions. I saw other SwiftUI questions and also an SwiftUI tag.
Anyway, it is like you explain but I could not find documentation that describes this way of working. It makes sense and is good to know that it works like this.

Thanks.

1 Like