A UI test case that checks for the existence of a SwiftUI Text element initialized with an empty string previously reliably passed in iOS 17.
In iOS 18 the assertion reliably fails.
I searched the iOS 18 developer release notes for anything possibly related to this but didn't find much. I'd like to point to a conclusive change in iOS handling before changing the test permantently. Can anyone confirm that this is indeed a change in iOS 18?
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
ScrollView scrolling works on Mac Catalyst apps with a Trackpad just fine but the same cannot be said for mouses with scroll wheels.
Is there any way to achieve scrolling with scroll wheels?
Buttons placed in the bottomBar and keyboard toolbar item positions in an inspector appear disabled/grayed out when at the large presentation detent.
The same is not true for sheets.
Is this intentional or a bug? If intentional, is there any backing design theory in the Human Interface Guidelines for it?
Xcode 16.4 / 18.5 simulator
// Inspector @ large detent
struct ContentView: View {
var body: some View {
Color.clear
.inspector(isPresented: .constant(true)) {
Color.clear
.presentationDetents([.large])
.toolbar {
ToolbarItem(placement: .bottomBar) {
Button("Save") {}
.border(.red)
}
}
}
}
}
// Sheet
struct ContentView: View {
var body: some View {
Color.clear
.sheet(isPresented: .constant(true)) {
Color.clear
.presentationDetents([.medium])
.toolbar {
ToolbarItem(placement: .bottomBar) {
Button("Save") {}
.border(.red)
}
}
}
}
}
Calls to NavigationPath.removeLast(_:) will successfully remove items from the path, but the navigation stack UI fails to correctly update if a view in an intermediate path item had a focused searchable modifier.
In this first video, the searchable modifier is unused. I can navigate to the list, make a selection and return home:
In this second example, the searchable modifier is focused and a selection from the list is made. In the final screen, if I attempt to return home we can see that the navigation path size decreases but the view does not change. If the button is pressed again, we attempt to remove path items that no longer exist, causing a fatal error.
Minimal Reproducible Code:
import SwiftUI
@main
struct NavigationStackRemoveLastNBugApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
struct ContentView: View {
@State private var navigationPath = NavigationPath()
var body: some View {
NavigationStack(path: $navigationPath) {
List {
Button("List") {
navigationPath.append(NavigationDestination.listView)
}
}
.navigationDestination(for: NavigationDestination.self) { destination in
switch destination {
case let .selectionView(int):
SelectionView(selectedNumber: int)
case .listView:
ListView()
}
}
.navigationTitle("Home")
}
.environment(\.navigationPath, $navigationPath)
}
}
enum NavigationDestination: Hashable {
case listView
case selectionView(Int)
}
struct ListView: View {
@Environment(\.navigationPath) var navigationPath
@State private var query = ""
var body: some View {
List(1..<5, id: \.self) { int in
Button {
navigationPath?.wrappedValue.append(NavigationDestination.selectionView(int))
} label: {
Text(int, format: .number)
}
}
.searchable(text: $query, placement: .navigationBarDrawer(displayMode: .always))
}
}
struct SelectionView: View {
@Environment(\.navigationPath) var navigationPath
let selectedNumber: Int
@State private var pathSize: Int?
var body: some View {
List {
LabeledContent("Selection", value: selectedNumber.formatted())
if let pathSize {
LabeledContent("Navigation Path Size", value: pathSize.formatted())
}
Button("Back Home") {
navigationPath?.wrappedValue.removeLast(2)
pathSize = navigationPath?.wrappedValue.count
}
}
.task {
pathSize = navigationPath?.wrappedValue.count
}
}
}
extension EnvironmentValues {
@Entry var navigationPath: Binding<NavigationPath>?
}
#Preview {
ContentView()
}
FB20395585