okta-mobile-swift icon indicating copy to clipboard operation
okta-mobile-swift copied to clipboard

Use of SwiftUI's `@Environment(\.dismiss)` causes infinite loop if okta-mobile-swift is listed as a dependency

Open NiallBegley opened this issue 7 months ago • 0 comments

Describe the bug?

I've run into a very particular bug where a SwiftUI iOS app will freeze and the CPU and memory usage will rapidly climb in a way consistent with something infinitely looping. It happens under these circumstances:

  • Project has the okta-mobile-swift dependency (just needs to be listed as a dependency, it doesn't need to be used or included anywhere)
  • View has the @Environment(\.dismiss) private var dismiss variable defined (doesn't even need to be used)
  • View has a NavigationLink to another View that must have a class member variable, usually this would be a view model. (structs do not cause the crash).

When the user presses the control associated with the NavigationLink the app will immediately freeze and resource consumption will rapidly climb. If you remove any of the above variables (including the use of okta-mobile-swift as a dependency) the freeze will disappear.

What is expected to happen?

When the NavigationLink is pressed the view should be pushed to the destination view as usual

What is the actual behavior?

The app immediately freezes and resource consumption climbs. You can put a breakpoint on the NavigationLink and see it keeps getting called over and over again.

Reproduction Steps?

  1. Create a new iOS SwiftUI project from scratch.
  2. Add the okta-mobile-swift dependency to the project (I used the latest version)
  3. If not already configured to do so, configure the app to use RootView as the root view and add the following code:
import SwiftUI

struct SystemCell: View {
    var body: some View {
        VStack(alignment: .leading) {
            Text("Unnamed System")
                .font(.headline)
                .foregroundColor(.primary)
                .lineLimit(1)
        }
    }
}

struct RootView: View {
    var body: some View {
        ZStack {
            NavigationStack {
                List {
                    NavigationLink(destination: SystemView()
                    ) {
                        SystemCell()
                    }
                }
            }
        }
        .padding()
    }
}

struct SystemView: View {
    @Environment(\.dismiss) private var dismiss
    var body: some View {
        VStack {
            NavigationView {
                NavigationLink {
                    HuhView(object: SimpleViewModel())
                } label: {
                    Image(systemName: "magnifyingglass")
                }
            }
        }
    }
}

struct HuhView: View {
    let object: SimpleViewModel
    var body: some View {
        Text("Huh")
    }
}

class SimpleViewModel { }
  1. Run the app, select the cell that appears, then click the magnifying glass on the next screen.

Additional Information?

No response

SDK Version(s)

Verified on 1.3.0 and 1.5.0

Build Information

No response

NiallBegley avatar Dec 13 '23 14:12 NiallBegley