1

Is this a bug in SwiftUI? If you tap "Test" it goes into a loop, putting up sheet after sheet forever. I can't see why.

This is happening on iOS and iPadOS 15

struct ContentView: View {
    
    @State private var showSheet = false
    @State private var name: String = ""
    @FocusState private var isFocused: Bool
    
    var body: some View {
        VStack {
            Button("Test") { setState() }
        }
        .sheet(isPresented: $showSheet) {
            VStack {
                Text("\(showSheet.description), \(name)")
                TextField("folder name", text: $name)
                    focused($isFocused)
            }
        }
    }

    private func setState() {
        print("setState")
        showSheet = true
    }
}
Rob N
  • 15,024
  • 17
  • 92
  • 165

1 Answers1

5

This is a typo, and normally should be just closed as such, but I think the reason is interesting enough to warrant an answer here:

struct ContentView: View {
    
    @State private var showSheet = false
    @State private var name: String = ""
    @FocusState private var isFocused: Bool
    
    var body: some View {
        VStack {
            Button("Test") { setState() }
        }
        .sheet(isPresented: $showSheet) {
            VStack {
                Text("\(showSheet.description), \(name)")
                TextField("folder name", text: $name)
                    focused($isFocused) //<-- THIS LINE IS MISSING A `.` -- it should be .focused($isFocused)
            }
        }
    }

    private func setState() {
        print("setState")
        showSheet = true
    }
}

Because you've omitted a . on the focused line, focused is returning a modifier on ContentView itself rather than on the TextField. That means that it's adding a copy of ContentView to the view hierarchy below TextField (since focused returns a modified version of self) rather than modifying the TextField in place.

This is causing the loop, but because technically it's valid code, it doesn't generated a compiler error.

jnpdx
  • 45,847
  • 6
  • 64
  • 94
  • Ha! Thanks. I've done this same thing once or twice before - left out the `.` on a modifier and had a very strange result that was hard to track down. I wonder if the compiler could be made to help here, with a warning. – Rob N Sep 28 '21 at 22:59
  • Yeah, it's an interesting question. I guess it could warn you if you're returning a copy of `self` inside the hierarchy, but there might actually be valid reasons for doing that (such as in view modifier code, rather than just in a view itself). – jnpdx Sep 28 '21 at 23:10
  • Great answer, deserves a +50 – Petru Lutenco May 05 '23 at 11:47