How to use allowedContentTypes for the NSOpenPanel in macOS?
Asked Answered
A

1

6

I'm trying to show the file picker window from my macOS GUI app written with SwiftUI. So I call this:

let panel = NSOpenPanel()

//panel.allowedFileTypes = ["myext"]    //I get a warning here that it's deprecated

//Trying to use the following instead:
let fileType = UTType(tag: "myext", tagClass: .filenameExtension, conformingTo: nil)
if(fileType != nil)
{
    panel.allowedContentTypes = [fileType!]
}
else
{
    assert(false)
}

panel.allowsMultipleSelection = false
panel.canChooseDirectories = false
panel.canChooseFiles = true

let resp = panel.runModal()

The panel is shown, but I can't select any file, including the ones with my .myext extension.

But if I uncomment panel.allowedFileTypes line, everything works as I expected.

So what am I doing wrong with that allowedContentTypes?

PS. Or, at least how do I mute that deprecated warning in Swift? (The allowedFileTypes works fine, what's the point of deprecating it!)

Averi answered 9/4, 2023 at 16:53 Comment(3)
Have you defined the file type for your app in the Info.plist?Jourdan
@JoakimDanielson: no. The issue was that it expected conformingTo: .data instead of the nil - I don't think it's in the documentation?Averi
This use of “conforms to” is touched upon in Uniform Type Identifiers — a reintroduction.Fossette
F
6

If it is your own extension, add an “exported type identifier”. If it is a type defined by another app, add an “imported type identifier”.

We can define type identifiers in the “Info” tab of the target settings. That will create/update the Info.plist accordingly. For example, if it is an exported identifier:

Target settings » Info » exported type identifiers

Please make a note of the “identifier”, the associated “extensions”, and the “conforms to” settings.

Having done that, we can now use that identifier in our code. Because this example was an “Exported Type Identifier”, we would use UTType(exportedAs:):

extension UTType {
    public static let foo = UTType(exportedAs: "com.domain.foo")
}

And then:

let panel = NSOpenPanel()

panel.allowedContentTypes = [.foo]
panel.allowsMultipleSelection = false
panel.canChooseDirectories = false
panel.canChooseFiles = true

let response = panel.runModal()

foo, bar, and baz files

For more information, see Apple “Tech Talk” video, Uniform Type Identifiers — a reintroduction.

Fossette answered 9/4, 2023 at 19:26 Comment(1)
Great answer! Note: dont't forget to import UniformTypeIdentifiersHanselka

© 2022 - 2024 — McMap. All rights reserved.