Last active
February 12, 2025 19:07
-
-
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// 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) | |
} | |
} |
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
}
}
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
How do you call this from another file to show the view?