Hello, After a fair amount of time of trial and error, I have seemingly discovered a bug in iOS 18 with .toolBar with placement:. keyboard)
Feedback: FB15205988
Xcode Version: 16.0 (16A242d)
iOS Version: 18.0 (22A3351)
I'd appreciate help to see if I'm missing something here.
What's happening?
When using .toolBar with (placement: .keyboard), within a NavigationSplitView detail:, encompassed in a TabView, the .toolBar view does not appear above the keyboard.
Within the code, the usage of .toolBar is within ShakeDetail.swift.
When commenting out the TabView within ShakeTabView.swift, or running on iOS 17.5, the .toolbar appears.
Would greatly appreciate help if someone knows a workaround, or a misunderstanding here of course!
Code
Shake.swift
import Foundation
import SwiftUI
struct Shake: Equatable, Identifiable, Hashable {
var name: String
let id = UUID()
static var example = Shake(name: "Banana")
static var many: [Shake] {
return [
Shake(name: "Apple"),
Shake(name: "Banana"),
Shake(name: "Cherry"),
Shake(name: "Berry"),
]
}
}
ShakeDetail.swift
import SwiftUI
struct ShakeDetail: View {
@State var shake: Shake = Shake(name: "")
var body: some View {
List {
TextField("dsf", text: $shake.name, prompt: Text("Enter your favorite shake"))
}
.scrollDismissesKeyboard(.interactively)
.toolbar {
ToolbarItem(placement: .keyboard) {
HStack(alignment: .center) {
Text(shake.name)
.font(.title3)
.foregroundColor(.red)
}
}
}
.toolbarColorScheme(.dark, for: .navigationBar)
.toolbarBackground(
Color.purple,
for: .navigationBar
)
.toolbarBackground(.visible, for: .navigationBar)
}
}
#Preview {
ShakeDetail()
}
ShakeListView.swift
struct ShakeListView: View {
@Binding var shakes: [Shake]
@Binding var selectedShake: Shake?
var body: some View {
List(selection: $selectedShake) {
ForEach(shakes) { shake in
NavigationLink(value: shake) {
Text(shake.name)
.font(.system(.title2, design: .rounded))
.foregroundStyle(.primary)
}
}
}
.navigationTitle("Shakes")
}
}
#Preview {
@Previewable @State var shakes: [Shake] = Shake.many
@Previewable @State var selectedShake: Shake?
ZStack {
ShakeListView(shakes: $shakes, selectedShake: $selectedShake)
}
}
ShakeSplitView.swift
import SwiftUI
import OSLog
public struct ShakeSplitView: View {
@State var selectedShake: Shake?
@State var shakes = Shake.many
@State private var columnVisibility = NavigationSplitViewVisibility.doubleColumn
public init(isShowingFavorites: Bool = false, columnVisibility: SwiftUI.NavigationSplitViewVisibility = NavigationSplitViewVisibility.doubleColumn) {
self.columnVisibility = columnVisibility
}
public var body: some View {
NavigationSplitView(columnVisibility: $columnVisibility) {
ShakeListView(shakes: $shakes, selectedShake: $selectedShake)
} detail: {
if let selectedShake {
// Add shake detail
ShakeDetail(shake: selectedShake)
} else {
Label("Please select a shake", systemImage: "arrow.backward.circle")
.foregroundColor(.purple)
.font(.system(.title2, design: .rounded))
}
}
.navigationSplitViewStyle(.balanced)
}
}
struct FormulaSplitView_Previews: PreviewProvider {
static var previews: some View {
ShakeSplitView()
}
}
ShakeTabView.swift
import SwiftUI
struct ShakeTabView: View {
var body: some View {
/* TabView breaks the ToolbarItem(placement: .keyboard) */
TabView {
ShakeSplitView()
.tabItem {
Image(systemName: "carrot.fill")
Text("Shakes")
}
}
}
}
#Preview {
ShakeTabView()
}