iOS Keyboard Toolbar disappearing when consecutive sheets are presented

When adding a Done button to the keyboard toolbar the toolbar presents and operates as expected on the first view. If you present multiple views using .sheet() once on top of the other, with each keyboard using the same toolbar and Done button, when you get to the third view that has been presented, the toolbar disappears.

I have tried adding a FocusState, FocusValue, NavigationStack and NavigationView, I have tried making sure the field state is cleared and contained within every view but nothing seems to work.

Tested on Version 15.4 iPhone 15 pro sim

import UIKit
import SwiftUI

struct ContentView: View {
    
    @Environment(\.dismiss) var dismiss
    
    @State var isPresenting: Bool = false
    @State var text: String = ""
    
    var body: some View {
        
        NavigationStack {
            VStack(alignment: .leading, spacing: 32) {
                
                TextField("Enter text", text: $text)
                    .padding(.top, 20)
                    .padding(.horizontal, 20)
                
                Button {
                    isPresenting.toggle()
                } label: {
                    Text("Present View")
                }
                .frame(maxWidth: .infinity, alignment: .center)
                .padding(.top, 40)
                
                Spacer()
            }
            .toolbar {
                
                toolbarContent
            }
            .sheet(isPresented: $isPresenting) {
                
                SecondView()
            }
        }
    }
    
    @ToolbarContentBuilder
    var toolbarContent: some ToolbarContent {
        
        ToolbarItemGroup(placement: .keyboard) {
            KeyboardAccessoryDone(title: "Done Content")
        }
    }
}

struct SecondView: View {
    
    @Environment(\.dismiss) var dismiss
    
    @State var isPresenting: Bool = false
    @State var text: String = ""
    
    var body: some View {
        
        NavigationStack {
            VStack(alignment: .leading, spacing: 32) {
                
                TextField("Enter text", text: $text)
                    .padding(.top, 20)
                    .padding(.horizontal, 20)
                
                Button {
                    isPresenting.toggle()
                } label: {
                    Text("Present View")
                }
                .frame(maxWidth: .infinity, alignment: .center)
                .padding(.top, 40)
                
                Spacer()
            }
            .toolbar {
                
                toolbarContent
            }
            .sheet(isPresented: $isPresenting) {
                
                ThirdView()
            }
        }
    }
    
    @ToolbarContentBuilder
    var toolbarContent: some ToolbarContent {
        
        ToolbarItem(placement: .topBarLeading) {
            CancelButton {
                dismiss()
            }
        }
        
        ToolbarItemGroup(placement: .keyboard) {
            KeyboardAccessoryDone(title: "Done Second")
        }
    }
}

struct ThirdView: View {
    
    @Environment(\.dismiss) var dismiss
    
    @State var isPresenting: Bool = false
    @State var text: String = ""
    
    var body: some View {
        
        NavigationStack {
            VStack(alignment: .leading, spacing: 32) {
                
                TextField("Enter text", text: $text)
                    .padding(.top, 20)
                    .padding(.horizontal, 20)
                
                Button {
                    isPresenting.toggle()
                } label: {
                    Text("Present View")
                }
                .frame(maxWidth: .infinity, alignment: .center)
                .padding(.top, 40)
                
                Spacer()
            }
            .toolbar {
                
                toolbarContent
            }
            .sheet(isPresented: $isPresenting) {
                
                FourthView()
            }
        }
    }
    
    @ToolbarContentBuilder
    var toolbarContent: some ToolbarContent {
        
        ToolbarItem(placement: .topBarLeading) {
            CancelButton {
                dismiss()
            }
        }
        
        ToolbarItemGroup(placement: .keyboard) {
            KeyboardAccessoryDone(title: "Done Third")
        }
    }
}

struct FourthView: View {
    
    @Environment(\.dismiss) var dismiss
    
    @State var isPresenting: Bool = false
    @State var text: String = ""
    
    var body: some View {
        
        NavigationStack {
            VStack(alignment: .leading, spacing: 32) {
                
                TextField("Enter text", text: $text)
                    .padding(.top, 20)
                    .padding(.horizontal, 20)
                
                Button {
                    isPresenting.toggle()
                } label: {
                    Text("Present View")
                }
                .frame(maxWidth: .infinity, alignment: .center)
                .padding(.top, 40)
                
                Spacer()
            }
            .toolbar {
                
                toolbarContent
            }
        }
    }
    
    @ToolbarContentBuilder
    var toolbarContent: some ToolbarContent {
        
        ToolbarItem(placement: .topBarLeading) {
            CancelButton {
                dismiss()
            }
        }
        
        ToolbarItemGroup(placement: .keyboard) {
            KeyboardAccessoryDone(title: "Done Forth")
        }
    }
}

public struct KeyboardAccessoryDone: View {

    // MARK: - Properties
    
    private let title: String
    private let onPress: (() -> ())?
    
    // MARK: - Init
    
    public init(
        title: String,
        onPress: (() -> ())? = nil
    ) {
        self.title = title
        self.onPress = onPress
    }
    
    // MARK: - View
    
    public var body: some View {
        
        Spacer()
        
        Button(title) {
            
            if let onPress {
                /// If the consumer of this view has chosen to inject a completion closure, then call it.
                onPress()
            } else {
                /// If the consumer of this view has omitted to inject a completion closure, then close the keyboard by calling `endEditing`.
                UIApplication.shared.endEditing()
            }
        }
    }
}

public struct CancelButton: View {
    
    private var onPress: (() -> Void)
    
    public init(
        onPress: @escaping () -> Void
    ) {
        self.onPress = onPress
    }
    
    public var body: some View {
        
        Button {
            onPress()
        } label: {
            Text("Cancel")
        }
        .accessibilityIdentifier("cancelButton")
    }
}

extension UIApplication {
    func endEditing() {
        sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
    }
}
Answered by DTS Engineer in 799176022

@B4DG3R Do you mind testing on the beta iOS 18.0 Beta 4? I was unable to reproduce the issue in the beta build.

Accepted Answer

@B4DG3R Do you mind testing on the beta iOS 18.0 Beta 4? I was unable to reproduce the issue in the beta build.

iOS Keyboard Toolbar disappearing when consecutive sheets are presented
 
 
Q