6

Is there a way to get All of the different UTType extension types as Strings? I need them specifically for images, audio, and video.

I followed this answer, but it doesn't give me all of the extensions

var types = [String]()

let utiTypes = [kUTTypeImage, kUTTypeMovie, kUTTypeVideo, kUTTypeMP3, kUTTypeAudio, kUTTypeQuickTimeMovie, kUTTypeMPEG, kUTTypeMPEG2Video, kUTTypeMPEG2TransportStream, kUTTypeMPEG4, kUTTypeMPEG4Audio, kUTTypeAppleProtectedMPEG4Audio, kUTTypeAppleProtectedMPEG4Video, kUTTypeAVIMovie, kUTTypeAudioInterchangeFileFormat, kUTTypeWaveformAudio, kUTTypeMIDIAudio, kUTTypeLivePhoto, kUTTypeTIFF, kUTTypeGIF, kUTTypeQuickTimeImage, kUTTypeAppleICNS]

for type in utiTypes {
            
    let str = String(type)
            
    guard let utiStr = fileExtension(for: str) else { continue }

    types.appent(utiStr)
}

dump(types)

The results are

15 elements // there are really 21 types
  - "jpeg"
  - "png"
  - "mov"
  - "mpg"
  - "m2v"
  - "ts"
  - "mp3"
  - "mp4"
  - "mp4"
  - "avi"
  - "aiff"
  - "wav"
  - "midi"
  - "tiff"
  - "gif"

The issue here is it doesn't return values like qt or jpg. For example I use the UIDocumentPickerViewController and when I select an image the returned url pathExtension is jpg not jpeg. If I wanted to know if the returned url was an image, and I compared its pathExtension to the types array above, it would say that it doesn't appear in the list.

Evgeny Karkan
  • 8,782
  • 2
  • 32
  • 38
Lance Samaria
  • 17,576
  • 18
  • 108
  • 256

3 Answers3

6

You can do:

import UniformTypeIdentifiers

let utiTypes = [UTType.image, .movie, .video, .mp3, .audio, .quickTimeMovie, .mpeg, .mpeg2Video, .mpeg2TransportStream, .mpeg4Movie, .mpeg4Audio, .appleProtectedMPEG4Audio, .appleProtectedMPEG4Video, .avi, .aiff, .wav, .midi, .livePhoto, .tiff, .gif, UTType("com.apple.quicktime-image"), .icns]

print(utiTypes.flatMap { $0?.tags[.filenameExtension] ?? [] })

There are 33 file extensions in total for the UTTypes that you have listed when I run this code in a playground. Note that some UTTypes you have listed have no file name extensions associated with them, probably because they are too "generic" (e.g. "image" and "video"). And some UTTypes have multiple file name extensions, and some may be the same with the file name extensions of other UTTypes.

There is no "jpg" or "png" in the output. To see them appear, you will have to use this list:

// I've also removed the types that have no file name extensions
let utiTypes = [
    UTType.jpeg,
    .png,
    .mp3,
    .quickTimeMovie,
    .mpeg,
    .mpeg2Video,
    .mpeg2TransportStream,
    .mpeg4Movie,
    .mpeg4Audio,
    .appleProtectedMPEG4Audio,
    .avi,
    .aiff,
    .wav,
    .midi,
    .tiff,
    .gif,
    UTType("com.apple.quicktime-image"),
    .icns
]

Using the above list, the output for me is:

jpeg
jpg
jpe
png
mp3
mpga
mov
qt
mpg
mpeg
mpe
m75
m15
m2v
ts
mp4
mpg4
mp4
mpg4
m4p
avi
vfw
aiff
aif
wav
wave
bwf
midi
mid
smf
kar
tiff
tif
gif
qtif
qti
icns

Also note that if you want to get the UTType from a file name extension, you can just do:

let type = UTType(tag: "jpg", tagClass: .filenameExtension, conformingTo: nil)

and check whether the file name extension is e.g. that of an image by doing:

type?.isSubtype(of: .image)

Though bear in mind that the file does not necessarily represent an image just because its name says it is :)

Sweeper
  • 213,210
  • 22
  • 193
  • 313
  • @LanceSamaria I've updated with a list of UTTypes that does give you "jpg" and "png". – Sweeper Nov 24 '21 at 21:00
  • thanks it worked. About what you said in your answer. Why wouldn't it be an image the file extension says image? Would that also apply for .movie? – Lance Samaria Nov 24 '21 at 21:02
  • For iOS 14 UTTypes, there are UTType.movie, UTType.video, UTType.audio, .rawVideo, .liveVideo. Does it apply for these meaning just because it says video and movie, doesn't mean that it's a video or movie? – Lance Samaria Nov 24 '21 at 21:04
  • 1
    @LanceSamaria It's just a file name, after all. I can change it to whatever I want, regardless of the contents of the file. I can totally create a text file and call it `cat.png`. Basically, I'm saying the same thing as the warning in the [documentation here](https://developer.apple.com/documentation/uniformtypeidentifiers/uttype/3551510-init). You should also use some other metric to determine the file type, if that is possible, otherwise you can't be 100% sure. – Sweeper Nov 24 '21 at 21:07
  • Ahhhhhh, you are are 100% correct, I overlooked that. THANK YOU for the advice :)!!! Do you have any SO links that I can use to check against that actual content itself? – Lance Samaria Nov 24 '21 at 21:08
  • @LanceSamaria You can read the file. Many file types have [signatures](https://en.wikipedia.org/wiki/List_of_file_signatures), and you can see how to check that [here](https://stackoverflow.com/questions/21789770/determine-mime-type-from-nsdata). – Sweeper Nov 24 '21 at 21:12
  • I’m looking at the links now. Thanks for your help! Happy Coding! – Lance Samaria Nov 24 '21 at 21:15
5

For those who are looking for all possible types - here is the full list as of iOS 15:

func allUTITypes() -> [UTType] {
        let types : [UTType] =
            [.item,
             .content,
             .compositeContent,
             .diskImage,
             .data,
             .directory,
             .resolvable,
             .symbolicLink,
             .executable,
             .mountPoint,
             .aliasFile,
             .urlBookmarkData,
             .url,
             .fileURL,
             .text,
             .plainText,
             .utf8PlainText,
             .utf16ExternalPlainText,
             .utf16PlainText,
             .delimitedText,
             .commaSeparatedText,
             .tabSeparatedText,
             .utf8TabSeparatedText,
             .rtf,
             .html,
             .xml,
             .yaml,
             .sourceCode,
             .assemblyLanguageSource,
             .cSource,
             .objectiveCSource,
             .swiftSource,
             .cPlusPlusSource,
             .objectiveCPlusPlusSource,
             .cHeader,
             .cPlusPlusHeader]

        let types_1: [UTType] =
            [.script,
             .appleScript,
             .osaScript,
             .osaScriptBundle,
             .javaScript,
             .shellScript,
             .perlScript,
             .pythonScript,
             .rubyScript,
             .phpScript,
             .makefile, //'makefile' is only available in iOS 15.0 or newer
             .json,
             .propertyList,
             .xmlPropertyList,
             .binaryPropertyList,
             .pdf,
             .rtfd,
             .flatRTFD,
             .webArchive,
             .image,
             .jpeg,
             .tiff,
             .gif,
             .png,
             .icns,
             .bmp,
             .ico,
             .rawImage,
             .svg,
             .livePhoto,
             .heif,
             .heic,
             .webP,
             .threeDContent,
             .usd,
             .usdz,
             .realityFile,
             .sceneKitScene,
             .arReferenceObject,
             .audiovisualContent]

        let types_2: [UTType] =
            [.movie,
             .video,
             .audio,
             .quickTimeMovie,
             UTType("com.apple.quicktime-image"),
             .mpeg,
             .mpeg2Video,
             .mpeg2TransportStream,
             .mp3,
             .mpeg4Movie,
             .mpeg4Audio,
             .appleProtectedMPEG4Audio,
             .appleProtectedMPEG4Video,
             .avi,
             .aiff,
             .wav,
             .midi,
             .playlist,
             .m3uPlaylist,
             .folder,
             .volume,
             .package,
             .bundle,
             .pluginBundle,
             .spotlightImporter,
             .quickLookGenerator,
             .xpcService,
             .framework,
             .application,
             .applicationBundle,
             .applicationExtension,
             .unixExecutable,
             .exe,
             .systemPreferencesPane,
             .archive,
             .gzip,
             .bz2,
             .zip,
             .appleArchive,
             .spreadsheet,
             .presentation,
             .database,
             .message,
             .contact,
             .vCard,
             .toDoItem,
             .calendarEvent,
             .emailMessage,
             .internetLocation,
             .internetShortcut,
             .font,
             .bookmark,
             .pkcs12,
             .x509Certificate,
             .epub,
             .log]
                .compactMap({ $0 })

        return types + types_1 + types_2
    }

Note: I've intentionally split data into 3 arrays to speed up compilation time.

Evgeny Karkan
  • 8,782
  • 2
  • 32
  • 38
0

You should not try to compare the extension of the URL returned by UIDocumentPickerViewController to a known list of extensions. Instead, use url.resourceValues(forKeys: [.contentTypeKey]).contentType to get a UTType for the returned URL, and then check that it conforms to .image: type.conforms(to: .image).

Thomas Deniau
  • 2,488
  • 1
  • 15
  • 15