4

What is the easiest and shortest way to determine the UTType of a Data object in Swift?

For images it can be done like this:

let imageSource = CGImageSourceCreateWithData(imageData as CFData, nil)
let imageType = CGImageSourceGetType(imageSource)
let isTypeGIF = UTTypeConformsTo(imageType, kUTTypeGIF)

But if the data type is unknown, is there a more generic approach?

Determining by the first byte does not produce an UTType, so not the solution I am looking for:

var c = UnsafeMutablePointer<UInt8>.allocate(capacity: 1)
let firstByte = data.getBytes(c, length: 1)
let isTypeGIF = c[0] == 0x47

Update

This solution does not work, as it identifies the PNG image data as common UTI public.data instead of public.image or more accurately public.png:

let imageData = UIImagePNGRepresentation(UIImage(named: "image")!)!
let url = URL(fileURLWithPath: NSTemporaryDirectory() + UUID().uuidString)
try? imageData.write(to: url, options: [.atomicWrite])              
let typeIdentifer = try? url.resourceValues(forKeys: [.typeIdentifierKey])
let uti = typeIdentifer?.typeIdentifier
let isGif = UTTypeConformsTo(uti as! CFString, kUTTypeGIF)
Manuel
  • 14,274
  • 6
  • 57
  • 130
  • Where is that data coming from? – Leo Dabus Nov 23 '17 at 15:51
  • 1
    @LeoDabus From a server that does not provide any more information on the type. – Manuel Nov 23 '17 at 15:53
  • 1
    You can try saving it to a temporary directory and get the type identifier from the resourceValues – Leo Dabus Nov 23 '17 at 15:56
  • @LeoDabus, can you elaborate please? – Manuel Nov 23 '17 at 15:56
  • 1
    https://stackoverflow.com/questions/28570627/how-to-find-file-uti-for-file-withouth-pathextension-in-a-path-in-swift/34772517?s=1|52.2650#34772517 – Leo Dabus Nov 23 '17 at 15:58
  • @LeoDabus Is the `typeIdentifierKey` compatible with `UTTypeConformsTo`? – Manuel Nov 23 '17 at 16:01
  • I don’t know. Can you post the link from where the data it is coming from? – Leo Dabus Nov 23 '17 at 16:02
  • @LeoDabus It's a private server, so I cannot disclose the URL. But since `typeIdentifierKey` is a Uniform type identifier (UTI) and `UTType` is an abstraction in the hierarchy of UTIs I'd assume the `UTType` methods are applicable to it. – Manuel Nov 23 '17 at 16:05
  • You could use https://github.com/rs/SDWebImage/blob/master/SDWebImage/NSData%2BImageContentType.m to help you identify the data type. – Larme Nov 23 '17 at 16:07
  • 1
    @Larme `SDWebImage` seems to use the two solution I posted in my questions. Which is not practicable for unknown non-image data types. – Manuel Nov 23 '17 at 16:10
  • Indeed but you can’t identify all kind of content. – Larme Nov 23 '17 at 16:10
  • @Larme It should be possible with LeoDabus' approach. – Manuel Nov 23 '17 at 16:12
  • @LeoDabus Unfortunately it doesn't work, see the update in my question. – Manuel Nov 23 '17 at 17:25
  • @Manuel have you tried using url session ? – Leo Dabus Nov 23 '17 at 17:30
  • While using url session have you tried checking the response mimetype or suggestedFilename? – Leo Dabus Nov 23 '17 at 17:32
  • @LeoDabus Haven't tried, but it is not an option, the data is usually fetched through an SDK, not directly by its URL. However I think it shouldn't make any difference since the data has to be identical. It worked when using a local video URL provided by a UIImagePickerController. So I suspect that the controller sets the typeIdentifier for the URL object. That would mean unless the URL's typeIdentifier is set manually, the URL object only differentiates between `UTI Concrete Types` such as data, directory, etc. – Manuel Nov 23 '17 at 17:41
  • @Manuel unrelated to your question but it is much easier to get the first byte of your data using just `data.first`. And don't forget to deallocate the UnsafeMutablePointer when using it. – Leo Dabus Nov 23 '17 at 20:36
  • @LeoDabus Is that possible? Is a manual deallocation still necessary then? It is currently done with `defer { c.deallocate(capacity: 1) }` – Manuel Nov 23 '17 at 20:40
  • You didn't show defer in your code. But I would just use `data.first` or `data.prefix(n)` to get n bytes from it. – Leo Dabus Nov 23 '17 at 20:42

0 Answers0