0

I am using this simple tool for previewing different files in my app, but none of them is being successfully previewed.

First time I try to preview any file it opens preview controller with message Unsupported file format, and any other time it just displays filename and word data(see images).

Here is the implementation(Pay attention on the print statements):

extension FileShareVC: QLPreviewControllerDataSource, QLPreviewControllerDelegate {
    func numberOfPreviewItems(in controller: QLPreviewController) -> Int {
        filesList.count
    }
    
    func previewController(_ controller: QLPreviewController, previewItemAt index: Int) -> QLPreviewItem {
        
        let url = NSURL(fileURLWithPath: filesList[index].filePath ?? "", isDirectory: false)
        print(filesList[index].filePath!)
        //prints file:///var/mobile/Containers/Data/Application/AB608864-C682-47BB-8396-2D456430879E/Documents/F9RIB62HBUAW.jpeg
        print("url: \(url)")
        //prints file:/var/mobile/Containers/Data/Application/AB608864-C682-47BB-8396-2D456430879E/Documents/F9RIB62HBUAW.jpeg -- file:///
        return url
    }
}

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        tableView.deselectRow(at: indexPath, animated: true)
                  
        let quickLookViewController = QLPreviewController()
        quickLookViewController.dataSource = self
        quickLookViewController.delegate = self
        quickLookViewController.currentPreviewItemIndex = indexPath.row
        present(quickLookViewController, animated: true)
    }

I am not sure why my url appends -- file:/// on the file path, maybe that causes the problem? img1 img2

stackich
  • 3,607
  • 3
  • 17
  • 41
  • because filesList is of array of File class which has a property filepath – stackich Aug 24 '21 at 21:50
  • check my post below – Leo Dabus Aug 24 '21 at 21:50
  • Also note that your app is sandboxed and its location will change on every launch. If you need to persist that info you should save only its name and directory and recompose your URL when needed. – Leo Dabus Aug 24 '21 at 22:11
  • hmm that is very good info about sandbox, but how can I change that? I am now storing my files in .libraryDirectory and then sending them to API. API returns me the filesList which contains the file paths which are no more valid, right? what's the solution? – stackich Aug 24 '21 at 22:17
  • The solution is not to store the whole path. Just the last part of it. Just discard the prefix of the string all the way up through the libraryDirectory path component. – Leo Dabus Aug 24 '21 at 22:19
  • ok so I should store only name.extension ? – stackich Aug 24 '21 at 22:20
  • 1
    This depends if you have subfolders or not. If you don't just save the lastPathComponent – Leo Dabus Aug 24 '21 at 22:21

1 Answers1

1

The issue is that you are using the wrong initializer. You are passing an absoluteString to the initializer that expects a path (your string contains the scheme file://). Btw calling filePath an absoluteString is misleading.

guard let url = URL(string: filesList[index].filePath ?? "") else {
    return // an alternate URL or a just create a fatalError
}

Also note that your app is sandboxed and its location will change on every launch. If you need to persist that info you should save only its name and directory and recompose your URL when needed.


edit update:

Note that you are not supposed to place your files directly to the library folder. file system basics

enter image description here

Leo Dabus
  • 229,809
  • 59
  • 489
  • 571
  • thanks Leo. I tried this version of url you provided, but still the same result. Maybe the problem is in the Sandbox you are talking about. , but how can I change that? I am now storing my files in .libraryDirectory and then sending them to API. API returns me the filesList which contains the file paths which are no more valid, right? what's the solution? – stackich Aug 24 '21 at 22:19
  • 1
    The best option is simply get the contents of your directory when your app starts – Leo Dabus Aug 24 '21 at 22:20
  • So if I understood you well, I should send to API just the name.extension since I don't have subfolders. Then after trying to preview the file with that name.extension that API returns me, I should try to find that file(its path) in the directory since this part "AB608864-C682-47BB-8396-2D456430879E" is changing on each app running? – stackich Aug 24 '21 at 22:27
  • however I will mark the answer as correct because it solved the "file://" problem – stackich Aug 24 '21 at 22:28
  • If all you need is the file name (lastPathComponent) just get the libraryDirectory url and append the file name to it. it needs to be done when executing the app – Leo Dabus Aug 24 '21 at 22:28
  • Note that you are not supposed to place your files directly to this folder. [file system basics](https://developer.apple.com/library/archive/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/FileSystemOverview/FileSystemOverview.html) – Leo Dabus Aug 24 '21 at 22:29
  • thanks! hm, I needed to store the files somewhere where users cannot access them directly, so I found that(.libraryDir) the best option. the idea was to save them there and save their path to the backend. later, user can preview or save them to Files app(.documents directory) if he wants. – stackich Aug 24 '21 at 22:34
  • 1
    That is correct but check the file system basics link. You are supposed to use the application support folder. Just create a subfolder there using your bundle id and place your files there. – Leo Dabus Aug 24 '21 at 22:35