Update: I have now been able to successfully reproduce the issue in a minimal app environment. See the new MyView.swift.
As the title suggests, My SwiftUI app crashes with 'NSInvalidArgumentException' only when a List
cell is tapped from a search bar.
My issue is this:
I have a List
that is declared .searchable
, which uses a navigation link to link to another List
, which is also declared .searchable
. The second list bring up a modal page with .sheet
The searching in the first list works fine. The second list, on the other hand, works fine if the user apps a row without searching. However, if the user searches in the search box, and then taps one of the filtered results, the app presents the modal page and loads everything, then crashes.
If I remove the NavigationView
from the popup, then the app no longer crashes. However, then the search bar from the view behind it carries on to the popup which I do not want.
Here is the error message from the console:
2022-05-21 08:34:38.579406-0700 MyApp[68653:3984705] [Presentation] Attempt to present <_TtGC7SwiftUI29PresentationHostingControllerVS_7AnyView_: 0x100baa2d0> on <_TtGC7SwiftUI19UIHostingControllerGVS_15ModifiedContentVS_7AnyViewVS_12RootModifier__: 0x100c08680> (from <_TtGC7SwiftUI19UIHostingControllerGVS_15ModifiedContentVS_7AnyViewVS_24NavigationColumnModifier__: 0x102d0bdf0>) which is already presenting <_TtGC7SwiftUI29PresentationHostingControllerVS_7AnyView_: 0x100b8f3f0>.
2022-05-21 08:34:38.579913-0700 MyApp[68653:3984705] [Presentation] Attempt to present <_TtGC7SwiftUI29PresentationHostingControllerVS_7AnyView_: 0x100bb3260> on <_TtGC7SwiftUI19UIHostingControllerGVS_15ModifiedContentVS_7AnyViewVS_12RootModifier__: 0x100c08680> (from <_TtGC7SwiftUI19UIHostingControllerGVS_15ModifiedContentVS_7AnyViewVS_24NavigationColumnModifier__: 0x102d0bdf0>) which is already presenting <_TtGC7SwiftUI29PresentationHostingControllerVS_7AnyView_: 0x100b8f3f0>.
2022-05-21 08:34:38.605787-0700 MyApp[68653:3984705] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Application tried to present modally a view controller <SwiftUI.SwiftUISearchController: 0x10119f000> that is already being presented by <_TtGC7SwiftUI19UIHostingControllerGVS_15ModifiedContentVVS_22_VariadicView_Children7ElementVS_24NavigationColumnModifier__: 0x100bac8b0>.'
*** First throw call stack:
(0x1c9b0dd78 0x1e2772734 0x1cc3b4e98 0x1cc1a1b68 0x1cc152210 0x1cc385898 0x1cc1239dc 0x1cc20cd38 0x1cc1200c8 0x100a18c6c 0x100a1a7bc 0x100a2ac68 0x100a2a7a4 0x1c9ac62f0 0x1c9a801f4 0x1c9a936b8 0x1e5b2d374 0x1cc3f8e88 0x1cc17a5ec 0x1d18ca640 0x1d17f8524 0x1d17d9810 0x1004da4c0 0x1004da570 0x100985ce4)
libc++abi: terminating with uncaught exception of type NSException
dyld4 config: DYLD_LIBRARY_PATH=/usr/lib/system/introspection DYLD_INSERT_LIBRARIES=/Developer/usr/lib/libBacktraceRecording.dylib:/Developer/usr/lib/libMainThreadChecker.dylib:/Developer/Library/PrivateFrameworks/DTDDISupport.framework/libViewDebuggerSupport.dylib
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Application tried to present modally a view controller <SwiftUI.SwiftUISearchController: 0x10119f000> that is already being presented by <_TtGC7SwiftUI19UIHostingControllerGVS_15ModifiedContentVVS_22_VariadicView_Children7ElementVS_24NavigationColumnModifier__: 0x100bac8b0>.'
terminating with uncaught exception of type NSException
(lldb)
_
Steps To Reproduce:
- Get sample code provide below
- Run the app
- Tap an item in the first list
- Search "1" in the search box in the next list
- Tap the first result
- The app should crash
_
Here is a sample app in which I was able to replicate the behavior.
Test_AppApp.swift:
import SwiftUI
@main
struct Test_AppApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
ContentView.swift:
import SwiftUI
struct ContentView: View {
@State var sheetIsPresented:Bool = false
@State var searchText:String = ""
struct item: Identifiable {
var id:String
var string:String
}
func getItems() -> Array<item> {
let items = ["Item 1", "Item 2", "Item 3", "Item 4"].map({ item(id: UUID().uuidString, string: $0) })
if searchText == "" {
return items
} else {
return items.filter({ $0.string.contains(searchText) })
}
}
var body: some View {
NavigationView {
List {
ForEach(getItems()) { item in
NavigationLink(item.string) {
NextView()
}
}
/*
.onDelete { index in
print("delete")
}
*/
}
.searchable(text: $searchText)
.navigationTitle("Test App")
.navigationBarTitleDisplayMode(.large)
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
NextView.swift:
import SwiftUI
struct NextView: View {
@State var sheetIsPresented:Bool = false
@State var searchText:String = ""
struct item: Identifiable {
var id:String
var string:String
}
func getItems() -> Array<item> {
let items = ["Item 1", "Item 2", "Item 3", "Item 4"].map({ item(id: UUID().uuidString, string: $0) })
if searchText == "" {
return items
} else {
return items.filter({ $0.string.contains(searchText) })
}
}
var body: some View {
List {
ForEach(getItems()) { item in
HStack {
Button {
sheetIsPresented = true
} label: {
HStack {
Image(systemName: "shippingbox")
Text(item.string)
.foregroundColor(Color.black)
}
}
.sheet(isPresented: $sheetIsPresented, content: {
MyView()
})
}
}
/*
.onDelete { index in
print("delete")
}
*/
}
.searchable(text: $searchText)
.navigationTitle("Test App")
}
}
struct NextView_Previews: PreviewProvider {
static var previews: some View {
NextView()
}
}
MyView.swift:
import SwiftUI
struct MyView: View {
var body: some View {
NavigationView {
List {
Text("Test")
}
}
.navigationBarTitle("Test Page")
}
}
struct MyView_Previews: PreviewProvider {
static var previews: some View {
MyView()
}
}