Skip to content

Instantly share code, notes, and snippets.

@bguidolim
Last active June 7, 2023 01:49
Show Gist options
  • Save bguidolim/78dc909a4884027c4d2dce2a04b4793e to your computer and use it in GitHub Desktop.
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

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

@bguidolim
Copy link
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
   }
}

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