Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SwiftUI ShareLink set file name

I'm using the ShareLink to share an FileDocument which contains a String. The FileDocument is conform to the Transferable protocol.

This is the FileDocument Struct:

struct TransferableDocument: FileDocument, Transferable {

  static var transferRepresentation: some TransferRepresentation
  {
      DataRepresentation(exportedContentType: .text) { log in
          log.convertToData()
      }
  }

  // tell the system to support only text
  static var readableContentTypes: [UTType] = [.text]

  // by default the document is empty
  var text = ""

  // this initializer creates a empty document
  init(initialText: String = "") {
      text = initialText
  }

  // this initializer loads data that has been saved previously
  init(configuration: ReadConfiguration) throws {
      if let data = configuration.file.regularFileContents {
          text = String(decoding: data, as: UTF8.self)
      }
  }

  // this will be called when the system wants to write the data to disk
  func fileWrapper(configuration: WriteConfiguration) throws -> FileWrapper {
      let data = Data(text.utf8)
      return FileWrapper(regularFileWithContents: data)
  }

  func convertToData() -> Data
  {
      return text.data(using: .ascii) ?? Data()
  }
}

And this is the ShareLink:

var doc: TransferableDocument
{
    return TransferableDocument(initialText: "I'm a String")
}

ShareLink(item: doc ,preview: SharePreview("logfile")) 
{
    Text("Share")
}

When using AirDrop, the filename is set to the SharePreview title, in this case "logfile". When sharing it to Apps like Mail, the filename is simply set to "text".

Is there any way to set a default filename?

like image 327
Patrick Avatar asked Jan 29 '26 21:01

Patrick


2 Answers

This is now working, starting from iOS 17:

extension MyDocument: Transferable {
    public static var transferRepresentation: some TransferRepresentation {
        DataRepresentation(contentType: .foo) { document in
           [...]
        } importing: { data in
           [...]
        }
        .suggestedFileName { document in
            document.bar
        }
    }
}

like image 196
jan Avatar answered Feb 01 '26 00:02

jan


There is a method: suggestedFileName

DataRepresentation(exportedContentType: .png) { layer in
    layer.pngData()
}
.suggestedFileName("Layer.png")

Update1:

It is compiling now with Xcode 14.3 with FileRepresentation. But I cant share a file with FileRepresentation on iOS 16.0 Simulator so I don't know it is working or not on iOS 16.0, however it works on iOS 16.1 Simpulator. On macOS there is no "Save to File" option in sharing popup so I don't know it is working or not. :(

I mentioned a bug with exportCondition in comments, and it is working as expected on iOS 16.4 and macOS 13.3.

Update 2:

The Transferable protocol still not working as expected yet.

  1. If you have multiple FileRepresentation and one of them has a suggestedFileName, that will be use with every FileRepresentation. Even when the exportingCondition of FileRepresentation with suggestedFileName returns false.
  2. exportingCondition cannot be used with Main Actor isolated object.

I think the suggestedFileName is also useless because cannot determine with transferable object (example a document name).

like image 42
feca Avatar answered Jan 31 '26 23:01

feca