SwiftUI Open and Save Panels

AppKit has the NSOpenPanel and NSSavePanel classes to let people choose files to open and save in Mac apps. What is the SwiftUI equivalent to NSOpenPanel and NSSavePanel?

SwiftUI has .fileImporter and .fileExporter modifiers to let people choose files to open and save. Apply the modifier to a SwiftUI view, such as a button or a menu item. The .fileImporter and .fileExporter modifiers are available on both iOS and Mac.

File Importers

You must provide the following to .fileImporter:

  • A Boolean value that determines whether or not to show the panel
  • A list of allowed file types to open
  • A completion handler that runs when the panel closes

The following code lets someone open an image file:

@State private var isImporting: Bool = false
    
Button(action: {
  isImporting = true
}, label: {
  Text("Import Image")
})
.fileImporter(isPresented: $isImporting, 
  allowedContentTypes: [.png, .jpeg, .tiff], 
  onCompletion: { result in
                
  switch result {
  case .success(let url):
    // url contains the URL of the chosen file.
    let newImage = createImage(imageFile: url)
  case .failure(let error):
    print(error)
  }
})

If the person chooses a file and clicks the Open button, the result is .success, and the file importer provides the URL of the chosen file for you.

File Exporters

You must provide the following to .fileExporter:

  • A Boolean value that determines whether or not to show the panel
  • The document to export
  • The file type for the exported file
  • A completion handler that runs when the panel closes

You can also supply a default file name to the file exporter.

The following code exports a document to EPUB:

@State private var isPublishing: Bool = false
    
Button(action: {
  isPublishing = true
}, label: {
  Text("Publish")
})
.fileExporter(isPresented: $isPublishing,
  document: book,
  contentType: .epub,
  defaultFilename: book.title) { result in
             
  switch result {
  case .success(let url):
    book.publishEPUB(location: url)
  case .failure(let error):
    print(error)
  }
}

If the person chooses a location to save the file and clicks the Export button, the result is .success, and the file exporter provides the URL of the chosen file for you to write data from your app to the file.

Get the Swift Dev Journal Newsletter

Subscribe and get exclusive articles, a free guide on moving from tutorials to making your first app, notices of sales on books, and anything I decide to add in the future.

    We won't send you spam. Unsubscribe at any time.