working with fileImporter in a list

I'm running into an issue trying to create a link to fileImporter as part of a list of options.

I have an enum of options that will be presented in a sidebar-style list menu:

Code Block
enum MenuOption: Identifiable, CaseIterable {
var id: Int { self.hashValue }
case import
case optionB
case optionC
case optionD
case optionE
@ViewBuilder
var destination: some View {
switch self {
case .import: ImportView(isPresented: .constant(true), progress: ImportProgress())
case .optionB: OptionBView()
// etc
}
}


And I am iterating over the enum as follows:

Code Block
struct SidebarMenuView: View {
@State private var selection : MenuOption? = nil
var body: some View {
List(selection: $selection) {
ForEach(MenuOption.allCases) { option in
Button(action: { self.selection = option} ) {
option.label
}
.sheet(item: $selection) { sheet in
sheet.destination
}
}
}
}
}


However, presenting fileImporter as its own view causes the interface to crash. It has to be attached to something as a view modifier. The workaround suggested on SO is to attach it to Color.clear:

Code Block
struct ImportView: View {
@Binding var isPresented: Bool
@ObservedObject var progress: ImportProgress
var body: some View {
Color.clear
.fileImporter(
isPresented: $isPresented,
allowedContentTypes: [ ... ],
allowsMultipleSelection: true) { result in
if let urls = try? result.get() {
do { // stuff }
}
}
}


But the result of is this that, after fileImporter has been dismissed, there's an empty sheet still displayed which has to be dismissed separately, and I can't find a way around that.
Answered by BabyJ in 663181022
I have run this code and it works as expected. Tapping import shows the file importer and the other rows shows a sheet.

You can refine the code and tailor it towards your app.
Code Block Swift
enum MenuOption: String, CaseIterable, Identifiable {
case `import`
case optionB
case optionC
case optionD
case optionE
var id: Int { hashValue }
@ViewBuilder
var destination: some View {
switch self {
case .optionB: OptionBView()
...
default: EmptyView()
}
}
}
Code Block Swift
struct SidebarMenuView: View {
@State private var selection: MenuOption?
@State private var showingImport = false
var body: some View {
List {
ForEach(MenuOption.allCases) { option in
Button(option.rawValue) {
switch option {
case .import: showingImport = true
default: selection = option
}
}
.sheet(item: $selection) { option in
option.destination
}
.fileImporter(isPresented: $showingImport, allowedContentTypes: [...], allowsMultipleSelection: true) { result in
if let urls = try? result.get() {
print("Got urls")
}
}
}
}
}
}

Accepted Answer
I have run this code and it works as expected. Tapping import shows the file importer and the other rows shows a sheet.

You can refine the code and tailor it towards your app.
Code Block Swift
enum MenuOption: String, CaseIterable, Identifiable {
case `import`
case optionB
case optionC
case optionD
case optionE
var id: Int { hashValue }
@ViewBuilder
var destination: some View {
switch self {
case .optionB: OptionBView()
...
default: EmptyView()
}
}
}
Code Block Swift
struct SidebarMenuView: View {
@State private var selection: MenuOption?
@State private var showingImport = false
var body: some View {
List {
ForEach(MenuOption.allCases) { option in
Button(option.rawValue) {
switch option {
case .import: showingImport = true
default: selection = option
}
}
.sheet(item: $selection) { option in
option.destination
}
.fileImporter(isPresented: $showingImport, allowedContentTypes: [...], allowsMultipleSelection: true) { result in
if let urls = try? result.get() {
print("Got urls")
}
}
}
}
}
}

Thank you! I will see what I can do!
working with fileImporter in a list
 
 
Q