I am using QLPreviewController to preview documents. But i do not know how to display document stored on a server.
You can't. QuickLook only works for local resource files. You would need to download the data asynchronously first, save it to the document directory or to a temporary folder and present the QLPreviewController from the main thread when finished:
edit/update:
Xcode 11.3.1 • Swift 5.1
ViewController.swift
import UIKit
import QuickLook
class ViewController: UIViewController, QLPreviewControllerDelegate, QLPreviewControllerDataSource {
let previewController = QLPreviewController()
var previewItems: [PreviewItem] = []
override func viewDidLoad() {
super.viewDidLoad()
let url = URL(string:"https://www.adobe.com/support/products/enterprise/knowledgecenter/media/c4611_sample_explain.pdf")!
quickLook(url: url)
}
func numberOfPreviewItems(in controller: QLPreviewController) -> Int { previewItems.count }
func quickLook(url: URL) {
URLSession.shared.dataTask(with: url) { data, response, error in
guard let data = data, error == nil else {
// in case of failure to download your data you need to present alert to the user
self.presentAlertController(with: error?.localizedDescription ?? "Failed to download the pdf!!!")
return
}
// you neeed to check if the downloaded data is a valid pdf
guard
let httpURLResponse = response as? HTTPURLResponse,
let mimeType = httpURLResponse.mimeType,
mimeType.hasSuffix("pdf")
else {
print((response as? HTTPURLResponse)?.mimeType ?? "")
self.presentAlertController(with: "the data downloaded it is not a valid pdf file")
return
}
do {
// rename the temporary file or save it to the document or library directory if you want to keep the file
let suggestedFilename = httpURLResponse.suggestedFilename ?? "quicklook.pdf"
var previewURL = FileManager.default.temporaryDirectory.appendingPathComponent(suggestedFilename)
try data.write(to: previewURL, options: .atomic) // atomic option overwrites it if needed
previewURL.hasHiddenExtension = true
let previewItem = PreviewItem()
previewItem.previewItemURL = previewURL
self.previewItems.append(previewItem)
DispatchQueue.main.async {
UIApplication.shared.isNetworkActivityIndicatorVisible = false
self.previewController.delegate = self
self.previewController.dataSource = self
self.previewController.currentPreviewItemIndex = 0
self.present(self.previewController, animated: true)
}
} catch {
print(error)
return
}
}.resume()
UIApplication.shared.isNetworkActivityIndicatorVisible = true
}
func previewController(_ controller: QLPreviewController, previewItemAt index: Int) -> QLPreviewItem { previewItems[index] }
func presentAlertController(with message: String) {
// present your alert controller from the main thread
DispatchQueue.main.async {
UIApplication.shared.isNetworkActivityIndicatorVisible = false
let alert = UIAlertController(title: "Alert", message: message, preferredStyle: .alert)
alert.addAction(.init(title: "OK", style: .default))
self.present(alert, animated: true)
}
}
}
ExtensionsURL.swift
extension URL {
var hasHiddenExtension: Bool {
get { (try? resourceValues(forKeys: [.hasHiddenExtensionKey]))?.hasHiddenExtension == true }
set {
var resourceValues = URLResourceValues()
resourceValues.hasHiddenExtension = newValue
try? setResourceValues(resourceValues)
}
}
}
PreviewItem.swift
import QuickLook
class PreviewItem: NSObject, QLPreviewItem {
var previewItemURL: URL?
}
You just need to subclass the QLPreviewController and add your functionality. I did it in my case, It waits for files to download from the server and then load those automatically.
My PreviewController Class
import UIKit
import QuickLook
class JSQuickPreviewController: QLPreviewController, QLPreviewControllerDataSource {
var fileName: String = ""
var url: URL?
private var previewItem : PreviewItem!
private let activityIndicator: UIActivityIndicatorView = {
let activityIndicator = UIActivityIndicatorView(style: .whiteLarge)
activityIndicator.translatesAutoresizingMaskIntoConstraints = false
activityIndicator.hidesWhenStopped = true
activityIndicator.tintColor = .black
activityIndicator.color = .black
activityIndicator.startAnimating()
return activityIndicator
}()
override func viewDidLoad() {
super.viewDidLoad()
self.dataSource = self;
self.view.addSubview(activityIndicator)
activityIndicator.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
activityIndicator.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
self.title = fileName;
self.downloadfile(fileName: fileName, itemUrl: url)
self.hideErrorLabel();
// Do any additional setup after loading the view.
}
@objc
func hideErrorLabel() {
var found = false
for v in self.view.allViews.filter({ $0 is UILabel }) {
v.isHidden = true
found = true
}
if !found {
self.perform(#selector(hideErrorLabel), with: nil, afterDelay: 0.1);
}
}
private func downloadfile(fileName:String, itemUrl:URL?){
self.previewItem = PreviewItem()
let documentsDirectoryURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
let destinationUrl = documentsDirectoryURL.appendingPathComponent(fileName)
if FileManager.default.fileExists(atPath: destinationUrl.path) {
self.previewItem.previewItemURL = destinationUrl;
self.loadFile()
}
else {
DispatchQueue.main.async(execute: {
if let itemUrl = itemUrl {
URLSession.shared.downloadTask(with: itemUrl, completionHandler: { (location, response, error) -> Void in
if error != nil {
for v in self.view.allViews.filter({ $0 is UILabel }) {
v.isHidden = false
(v as? UILabel)?.text = error?.localizedDescription
}
} else {
guard let tempLocation = location, error == nil else { return }
try? FileManager.default.moveItem(at: tempLocation, to: destinationUrl)
self.previewItem.previewItemURL = destinationUrl;
self.loadFile()
}
}).resume()
}
})
}
}
func loadFile() {
DispatchQueue.main.async {
self.activityIndicator.isHidden = true
self.reloadData()
}
}
func numberOfPreviewItems(in controller: QLPreviewController) -> Int {
return previewItem == nil ? 0 : 1
}
func previewController(_ controller: QLPreviewController, previewItemAt index: Int) -> QLPreviewItem {
return previewItem
}
}
extension UIView {
var allViews: [UIView] {
var views = [self]
subviews.forEach {
views.append(contentsOf: $0.allViews)
}
return views
}
}
How to use it
let quickPreviewController = JSQuickPreviewController()
quickPreviewController?.url = fileURL
quickPreviewController?.fileName = filename
self.show(quickPreviewController, animated: true)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.