1

I am new fairly new to swift development but am obsessed and in love with learning, I have not only dedicated myself to learning but I am starting to apply my knowledge and have built a small messaging app with the capability to select a file. I have successfully created the ability for future users of my app to send documents via the messaging system, and I am able to show the file name, type etc. However, I am struggling to understand (reading apple documentation and other community developer's posts regarding this) how to fetch a specific icon type from the iOS system based on the file's extension type (e.g. xlsx), let alone the UTIType (e.g. public.movie -> mp4, etc.).

If anyone has suggestions on how/where to facilitate this, I would like to set my current, generic file icon to a custom filetype, as the one in the attached image example below (PDF in example):

enter image description here

Tarun's answer was quick and very helpful in getting one step further, however, it returned this icon for pdf, png, and jpeg, all tested (regardless of the aforementioned differentiation in file type.

enter image description here

Here is my code:

guard let fileUrl = message.documentUrl else { return }
let fileNameUrl = (fileUrl as NSString).lastPathComponent
let fileName = fileNameUrl.components(separatedBy: "?")[0].removingPercentEncoding
    
let documentInteractionController = UIDocumentInteractionController()
documentInteractionController.name = fileName
documentInteractionController.url = URL(fileURLWithPath: fileNameUrl)
    
let fileTypeIcon = documentInteractionController.icons.first
fileIcon.image = fileTypeIcon

2 Answers2

1

You can use QuickLook Thumbnailing framework.Have a look at the Apple documentation. https://developer.apple.com/documentation/quicklookthumbnailing

Akilan C B
  • 199
  • 1
  • 9
0

When you get a file url from UIDocumentPickerViewController, you need to query it's uti / mimeType etc. which you can do from following helpers.

import Foundation
import MobileCoreServices

public extension URL {
    
    private var utiCFString: CFString? {
        UTTypeCreatePreferredIdentifierForTag(
            kUTTagClassFilenameExtension, 
            self.pathExtension as NSString,
            nil
        )?.takeRetainedValue()
    }
    
    var uti: String? {
        self.utiCFString as String?
    }
    
    var mimeType: String? {
        if let utiCFString = self.utiCFString {
            return UTTypeCopyPreferredTagWithClass(
                utiCFString, 
                kUTTagClassMIMEType
            )?.takeRetainedValue() as String?
        }
        return nil
    }
    
}


extension ViewController: UIDocumentPickerDelegate {
    
     func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) {
        
        guard let url = urls.first else { return }
            
        guard let mimeType = url.mimeType else {
            print("Invalid file type")
            return
        }

        let uti = url.uti
    }
}

Once you have all the info you need, you can try this -

let documentInteractionController = UIDocumentInteractionController()
documentInteractionController.name = filename
documentInteractionController.url = URL(fileURLWithPath: filePath)
documentInteractionController.uti = uti

let mayBeIcon = documentInteractionController.icons.last
Tarun Tyagi
  • 9,364
  • 2
  • 17
  • 30
  • Thanks for your quick answer, it seems very straight forward. I have another class which handles the visuals for the file icon types aside from the class where the document is selected. Does the 'icons.last' portion return a UIImage or a string? I would like to somehow display an icon for a string type, because I can't pass a UIImage through my database (obvious reasons). Just not sure how to go about showing an icon in another class for it. –  Jun 15 '21 at 16:39
  • 1
    You need `fileURL` / `fileName` values that you have as `String`. Whenever you want an icon, you create a new instance of `UIDocumentInteractionController`, set the file information on it, ask for the icons from it. It will return `[UIImage]`. Check out [UIDocumentInteractionController.icons](https://developer.apple.com/documentation/uikit/uidocumentinteractioncontroller/1616801-icons) – Tarun Tyagi Jun 15 '21 at 16:47
  • @NewDeveloper it returns an image if there is an icon available for the file type otherwise it returns a generic icon. Note that `last` will return the largest icon and `first` the smallest – Leo Dabus Jun 15 '21 at 16:47
  • Oh awesome, I didn't realize you could just call UIDocumentInteractionController from wherever. Thank you both very much! @LeoDabus –  Jun 15 '21 at 16:54
  • @both of you - I am unable to upvote your answers due my reputation being so low. Honestly, I feel this is a bit of a flaw in the stack overflow system considering it's my question. If you both could upvote my question, considering you both answered (and I am assume it does NOT violet the guidelines), please do so. It would be greatly appreciated. In turn, I will upvote both your answers. Thanks. –  Jun 15 '21 at 16:56
  • Unfortunately, I am not sure why, but it is only returning the generic file icon. –  Jun 15 '21 at 17:10
  • Does your fileURL / fileName have extension specified in the string value? – Tarun Tyagi Jun 15 '21 at 17:11
  • I updated the answer, perhaps you can help by providing another answer, if possible. Thank you for helping out with this. –  Jun 15 '21 at 17:16
  • 'documentUrl' from message.documentUrl is the file's url as an absoluteString. –  Jun 15 '21 at 17:17