Skip to content

Instantly share code, notes, and snippets.

@bguidolim
Last active February 12, 2025 19:07
Show Gist options
  • Select an option

  • Save bguidolim/78dc909a4884027c4d2dce2a04b4793e to your computer and use it in GitHub Desktop.

Select an option

Save bguidolim/78dc909a4884027c4d2dce2a04b4793e to your computer and use it in GitHub Desktop.
FilePreview is a easy way to open in-app some kind of files (PDF, DOC, XLS, TXT, images, etc) as read only. This is a simple implementation using WKWebView but with an interface to check if is possible to open the file before showing the ViewController.
//
// FilePreview.swift
// COYO Messenger Framework
//
// Created by Bruno Guidolim on 21.11.18.
// Copyright © 2018 COYO. All rights reserved.
//
import Foundation
import WebKit
final public class FilePreview: NSObject {
public typealias CompletionHandler = ((_ canShowFile: Bool, _ viewController: FilePreviewController?) -> Void)
private let webView: WKWebView
private let fileURL: URL
private var completionHandler: CompletionHandler?
init(fileURL: URL) {
self.fileURL = fileURL
self.webView = WKWebView(frame: .zero)
super.init()
webView.navigationDelegate = self
}
public func canShowFile(completion: CompletionHandler?) {
self.completionHandler = completion
self.webView.loadFileURL(self.fileURL, allowingReadAccessTo: self.fileURL.deletingLastPathComponent())
}
}
extension FilePreview: WKNavigationDelegate {
public func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
if let url = navigationAction.request.url, url != fileURL {
UIApplication.shared.open(url)
decisionHandler(.cancel)
return
}
decisionHandler(.allow)
}
public func webView(_ webView: WKWebView, decidePolicyFor navigationResponse: WKNavigationResponse, decisionHandler: @escaping (WKNavigationResponsePolicy) -> Void) {
if navigationResponse.canShowMIMEType {
let vc = FilePreviewController(webView: webView, title: fileURL.lastPathComponent)
completionHandler?(true, vc)
decisionHandler(.allow)
return
}
completionHandler?(false, nil)
decisionHandler(.cancel)
}
}
public protocol FilePreviewControllerDelegate: class {
func filePreviewControllerDidTapShareButton(_ viewController: UIViewController)
}
final public class FilePreviewController: UIViewController {
public weak var delegate: FilePreviewControllerDelegate?
private let webView: WKWebView
fileprivate init(webView: WKWebView, title: String) {
self.webView = webView
super.init(nibName: nil, bundle: nil)
self.title = title
}
required public init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override public func loadView() {
view = webView
}
override public func viewDidLoad() {
super.viewDidLoad()
if #available(iOS 11, *) {
webView.scrollView.contentInsetAdjustmentBehavior = .always
} else {
self.automaticallyAdjustsScrollViewInsets = true
}
let shareButton = UIBarButtonItem(barButtonSystemItem: .action, target: self, action: #selector(shareButtonTapped(_:)))
navigationItem.setRightBarButton(shareButton, animated: true)
}
@objc private func shareButtonTapped(_ sender: Any) {
delegate?.filePreviewControllerDidTapShareButton(self)
}
}
@willm132
Copy link
Copy Markdown

How do you call this from another file to show the view?

@bguidolim
Copy link
Copy Markdown
Author

bguidolim commented Jun 30, 2021

How do you call this from another file to show the view?

let filePreview = FilePreview(fileURL: fileURL)
filePreview.canShowFile { [weak self] canShowFile, fileViewController in
    if canShowFile {
        self?.present(fileViewController, animated: true)
   } else {
        // Share activity code for example
   }
}

@kmithi1-apps
Copy link
Copy Markdown

this is not loading file saved in document directory.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment