Reputation: 727
I'm Junior and currently working on project where Im in WKWebView and there are links to open pdf. I can open it in Safari and then open in iBooks, but i want it to do it inside my app. Is it possible ?
Here are pics how it looks like:
picture where i can select pdf
picture what it will open
class WebVC: UIViewController, WKUIDelegate {
var webView: WKWebView!
override func viewDidLoad() {
super.viewDidLoad()
let myURL = NSURL(string: "\(savedURL!)")
let myRequest = URLRequest(url: myURL! as URL)
webView.load(myRequest)
webView.allowsBackForwardNavigationGestures = true
webView.allowsLinkPreview = false
}
override func viewWillAppear(_ animated: Bool) {
self.navigationController?.toolbar.isHidden = false
}
override func loadView() {
let webConfiguration = WKWebViewConfiguration()
webView = WKWebView(frame: CGRect(x: 100, y: 100, width: 110, height: 110), configuration: webConfiguration)
webView.uiDelegate = self
view = webView
}
@IBAction func logoutPressed(_ sender: AnyObject) {
defaults.set(false, forKey: "isLogged")
defaults.set("EMPTY URL", forKey: "savedURL")
_ = self.navigationController?.popToRootViewController(animated: true)
}
@IBAction func goBack(_ sender: Any?) {
if (self.webView.canGoBack) {
self.webView.goBack()
}
}
}
Upvotes: 2
Views: 4356
Reputation: 146
To open pdf in webview
//step 1
webview.uiDelegate = self
//step 2 - implement delegate func (This function will let you open any clicked pdf in webview)
func webView(_ webView: WKWebView, createWebViewWith configuration: WKWebViewConfiguration, for navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView? {
// open in current view
webView.load(navigationAction.request)
// don't return a new view to build a popup into (the default behavior).
return nil;
}
Download
In my case once i have opened pdf in webview, i have download button which i use to download the current opened pdf
//step 3 - delegate funcs
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
decisionHandler(WKNavigationActionPolicy.allow)
}
//find the mimeTime of the current url opened in webview, If it's pdf, we'll give option to download
func webView(_ webView: WKWebView, decidePolicyFor navigationResponse: WKNavigationResponse, decisionHandler: @escaping (WKNavigationResponsePolicy) -> Void) {
if let mimeType = navigationResponse.response.mimeType {
//check if mime exists in our acceptable mimes list
if self.isMimeTypeConfigured(mimeType) {
self.mime = mimeType
self.currentUrl = navigationResponse.response.url
addDownloadButton()
}
}
decisionHandler(.allow)
}
//step 4 - Create a extension with helper functions
//=== PDF downloading ===
struct MimeType {
var type:String
var fileExtension:String
}
extension DownloadManual {
//button
private func addDownloadButton(){
let btn = UIBarButtonItem(image: UIImage(systemName: "tray.and.arrow.down.fill"), style: .plain, target: nil, action: #selector(downloadTapped))
self.navigationItem.rightBarButtonItem = btn
}
@objc func downloadTapped(){
self.showActivityIndicator(show: true)
if let url = currentUrl {
print("download from: \(url)")
let filename = getDefaultFileName(forMimeType: self.mime)
downloadData(fromURL: url, fileName: filename) { success, destinationURL in
if success, let destinationURL = destinationURL {
self.showActivityIndicator(show: false)
print("download result: \(success), \(destinationURL)")
self.fileDownloadedAtURL(url: destinationURL)
}
}
}
}
//helper funcs
private func isMimeTypeConfigured(_ mimeType:String) -> Bool {
for record in self.mimeTypes {
if mimeType.contains(record.type) {
return true
}
}
return false
}
func fileDownloadedAtURL(url: URL) {
print("downloaded at: \(url)")
DispatchQueue.main.async {
let activityVC = UIActivityViewController(activityItems: [url], applicationActivities: nil)
activityVC.popoverPresentationController?.sourceView = self.view
activityVC.popoverPresentationController?.sourceRect = self.view.frame
activityVC.popoverPresentationController?.barButtonItem = self.navigationItem.rightBarButtonItem
self.present(activityVC, animated: true, completion: nil)
}
}
private func downloadData(fromURL url:URL,
fileName:String,
completion:@escaping (Bool, URL?) -> Void) {
webview.configuration.websiteDataStore.httpCookieStore.getAllCookies() { cookies in
let session = URLSession.shared
print("downloading ....")
session.configuration.httpCookieStorage?.setCookies(cookies, for: url, mainDocumentURL: nil)
let task = session.downloadTask(with: url) { localURL, urlResponse, error in
if let localURL = localURL {
let destinationURL = self.moveDownloadedFile(url: localURL, fileName: fileName)
completion(true, destinationURL)
}
else {
completion(false, nil)
}
}
task.resume()
}
}
private func getDefaultFileName(forMimeType mimeType:String) -> String {
for record in self.mimeTypes {
if mimeType.contains(record.type) {
return "default." + record.fileExtension
}
}
return "default"
}
private func moveDownloadedFile(url:URL, fileName:String) -> URL {
let tempDir = NSTemporaryDirectory()
let destinationPath = tempDir + fileName
let destinationURL = URL(fileURLWithPath: destinationPath)
try? FileManager.default.removeItem(at: destinationURL)
try? FileManager.default.moveItem(at: url, to: destinationURL)
return destinationURL
}
HOPE this helps someone :)
Upvotes: 2
Reputation: 727
I solved it with UIDocumentInteractionController, add a button and when I push the button It will download whole page and then present DocumentController where "import to iBooks" option is. Hope it helps.
@IBAction func shareBtn(_ sender: AnyObject) {
var localPath: NSURL?
Alamofire.download(webView.url!, method: .get, parameters: nil, headers: nil) { (tempUrl, response) in
let directoryURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
let pathComponent = response.suggestedFilename
localPath = directoryURL.appendingPathComponent(pathComponent!) as NSURL?
return (destinationURL: localPath as! URL, options: .removePreviousFile)
}.response { response in
if localPath != nil{
self.docController = UIDocumentInteractionController(url: localPath! as URL)
self.docController.presentOptionsMenu(from: sender as! UIBarButtonItem, animated: true)
}
}
}
Upvotes: 1