FocusState not working as expected in iOS 17(Public Beta)

I've been testing my app on iOS 17 Public Beta and noticed a bug where the FocusState always returns nil depending on the combination of Views.

This issue did not occur on iOS 16 and earlier.

Below is the code where FocusState does not work.

As far as I've checked, the issue only occurs in the case below. Does anyone have a workaround?

Test environment:

  • Xcode Version 15.0 (15A240d)
  • iOS 17.0(21A329) (iPhone)

@main
struct SampleApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView() ///<-- 1
        }
    }
}

struct ContentView: View {
    @State var isShowingCover = false
    
    var body: some View {
        Button("Show") {
            isShowingCover = true
        }
        .fullScreenCover(isPresented: $isShowingCover) {
            NavigationStack {   ///<-- 2
                SheetView()
            }
        }
    }
}

struct SheetView: View {
    @State private var texts: [String] = [
        "file",
        "folder",
    ]
    @FocusState var focusing: Int?
    
    var body: some View {
        VStack {
            Text("focusing: \(String(describing: focusing))")
            List {  ///<-- 3
                TextFields(texts: $texts, focusing: $focusing)
            }
            Button(">") {
                // FocusState always becomes nil in iOS 17
                if let focusing { self.focusing = (focusing + 1) % texts.count } 
                else { self.focusing = 0 }
            }
        }
    }
}

public struct TextFields: View {
    
    @Binding var texts: [String]
    var focusing: FocusState<Int?>.Binding
    
    public var body: some View {
        HStack {
            ForEach(texts.indices, id: \.self) { idx in
                TextField("", text: $texts[idx])
                    .focused(focusing, equals: idx)
                    .underline(idx == focusing.wrappedValue)
            }
        }
    }
}

Interestingly, removing the NavigationStack within fullScreenCover makes FocusState work as expected. (2)

Also, if the ContentView in WindowGroup is changed to NavigationStack { SheetView() } (1) or the List (3) is removed, FocusState still works as expected.

/// 1
@main
struct MultilineFieldSampleApp: App {
    var body: some Scene {
        WindowGroup {
            // ContentView()
            NavigationStack {
                SheetView() // FocusState works.
            }
        }
    }
}

///2 
struct ContentView: View {
    
   @State var isShowingCover = false
    
    var body: some View {
        Button("Show") {
            isShowingCover = true
        }
        .fullScreenCover(isPresented: $isShowingCover) {
//             NavigationStack {
                  SheetView() // Also, FocusState works.
//             }
        }
    }
}

/// 3
struct SheetView: View {
    // ... 

    var body: some View {
        VStack {
            Text("focusing: \(String(describing: focusing))")
//            List {
                TextFields(texts: $texts, focusing: $focusing) // FocusState works.
//            }
            Button(">") {
                if let focusing { self.focusing = (focusing + 1) % texts.count }
                else { self.focusing = 0 }
            }
        }
    }
}

I have found the simplest workaround for this code: use NavigationView {}.navigationViewStyle(.stack) instead of NavigationStack.

However, using NavigationView may introduce other issues.

I posted FB13169518

Still an issue in Xcode 15 RC1.

I'm experiencing the same issue. In my case, there is no WindowGroup nor List, but we do have the NavigationStack deployed within fullScreenCover and the views subject to focus are within a ScrollView and ScrollViewReader.

It seems that this issue was fixed in iOS 17.1(21B74)

FocusState not working as expected in iOS 17(Public Beta)
 
 
Q