How to display PDF files from remote location on UIWebView using Swift? - ios

I'm trying to display a pdf file, using an iOS app, that is located on our website. Here's how I'm doing this:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
print("preparing segue")
if segue.identifier == "PdfWebView" {
print("Found segue")
let detailViewController = segue.destinationViewController as! PdfViewController
let myIndexPath = self.tableView.indexPathForSelectedRow!
let row = myIndexPath.row
//Pass selected cell title to next View
detailViewController.website = pdfLinks[row]
print("Website: ", detailViewController.website)
}
}
// This is on pdfViewController
// The webiste = http://www.example.com/some-pdf-document-to-display.pdf
if let website = website {
print("Getting pdf: ",website)
if let pdf = NSBundle.mainBundle().URLForResource(website, withExtension: "pdf", subdirectory: nil, localization: nil){
print(pdf) // <-- this is always nil
let req = NSURLRequest(URL: pdf)
webView.loadRequest(req)
self.view.addSubview(webView)
}
}
What am I doing wrong? Needless to say, this is my very first app that I'm developing.

If the file is not in your app you should not use NSBundle.
let pdfUrl = NSURL(string: website)
let req = NSURLRequest(URL: pdfUrl)
I'm also not sure why you are adding the webView subview to the view. Shouldn't that be done somewhere else? Shouldn't you push a controller with the webview instead?

File is not in your Bundle. Instead you can directly load the URL.
let website = "http://www.sanface.com/pdf/test.pdf"
let reqURL = NSURL(string: website)
let request = NSURLRequest(URL: reqURL!)
webView.loadRequest(request)

Related

Issue loading PDF for UIActivityViewController with .dataRepresentation()

I have what I thought was a simple View Controller to displayed a preloaded PDF file. The path to the PDF is passed into var pdfPath by the pervious controller.
I have an action/share button I'm trying to use for sharing and printing the PDF using PDFDocument.dataRepresentation(). According to multiple sources online, it should work, but I'm getting a strange error:
[Unknown process name] Failed to load
/System/Library/PrivateFrameworks/CorePDF.framework/Versions/A/CorePDF
Code:
import UIKit
import PDFKit
class PDFViewController: UIViewController {
#IBOutlet weak var ActionBarButton: UIBarButtonItem!
var pdfPath: String? = nil
override func viewDidLoad() {
super.viewDidLoad()
let pdfView = PDFView(frame: self.view.bounds)
self.view.addSubview(pdfView)
pdfView.autoScales = true
if let path = pdfPath {
let fileURL = Bundle.main.url(forResource: path, withExtension: "pdf")
pdfView.document = PDFDocument(url: fileURL!)!
}
}
#IBAction func ActionButtonPressed(_ sender: UIBarButtonItem) {
print("ActionButtonPressed():")
if let path = pdfPath {
let fileURL = Bundle.main.url(forResource: path, withExtension: "pdf")
let pdfDocument = PDFDocument(url: fileURL!)
guard let data = pdfDocument?.dataRepresentation() else {return}
let activityController = UIActivityViewController(activityItems: [data], applicationActivities: nil)
self.present(activityController, animated: true, completion: nil)
}
}
If anyone knows the answer to why this isn't working I'd be very grateful.
Rather than passing the data, you can pass the URL of the file, which UIActivityViewController will recognise and display share options accordingly.
let activityController = UIActivityViewController(activityItems: [fileURL], applicationActivities: nil)

How can I clear WKWebView when trying to add a new webView from unwind segue?

I have an app that uses at WKWebView to display local file paths. It segues to another view controller, then unwinds to the original controller, with a new html file path. I have got it loading the new file path but only after the index file flashes for a second. Anyway to clear this view?
override func viewWillAppear(_ animated: Bool) {
if unwindingFromPost == true {
let htmlPath = Bundle.main.path(forResource: "card/card", ofType: "html", inDirectory: "pickles_ui")
let url = URL(fileURLWithPath: htmlPath!)
let request = URLRequest(url: url)
webView.scrollView.bounces = false
webView.load(request)
} else {
let htmlPath = Bundle.main.path(forResource: "index", ofType: "html", inDirectory: "pickles_ui")
let url = URL(fileURLWithPath: htmlPath!)
let request = URLRequest(url: url)
webView.scrollView.bounces = false
webView.load(request)
}
}
}
You might have this behaviour because it might show the previous url in webview just like a second before loading the new one. I can suggest a workaround like, loading a blank view on your webView when view disappears (viewWillDisAppear method):
In your main viewController try adding following:
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
let url = URL(string: "about:blank")
let request = URLRequest(url: url!)
myGraphView.loadRequest(request)
}

WKWebView load request in device not working, but simulator is working

I have a question about WKWebview.
First, I have a UITabbarViewController(tab1, tab2), and two ViewControllers.
In ViewController1 have two button (button1, button2) which action is click the tabbar tab2 to present the ViewController2 and bring different url string.
In ViewController2 have a WKWebView, and load the request of url string.
I work fine in simulator, but build in device and work fine at first time and the then I tap the tabbar tab1 and back to ViewController1.
I click the button2 and present the ViewController2.
And I also set breakpoint, the WKWebview have run the load request function.
But the WKWebview also show me the button1 url content, not button2 url content. When I back and click button2 again, it's work. Why the WKWebView don't refresh at first time?
Thanks.
Xcode 9.4.1, device iOS 12.0.1(16A404)
class ViewController1: UIViewController {
#objc func btnTapped(sender: UIButton) {
if let vc = self.navigationController?.parent as? ViewController {
if let number = item?.number {
let domainPath = “\(customURL!.absoluteString)"
let extPath = "detail/\(number)/&topPageBack=list"
let encodestr = extPath.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)
let finalPath = domainPath.appending("/").appending(encodestr!)
if let url = URL(string: finalPath) {
vc.loadSpecificURL = url
}
vc.tabBarView.buttonClick(tag: 1)
}
}
}
}
class ViewController2: UIViewController {
lazy var webViewController: CustomWKWebViewController = {
let controller = CustomWKWebViewController()
controller.wKWebViewPage = .searchPage
return controller
}()
var loadURL: URL?
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
if let url = loadURL {
webViewController.reloadWebView(url: url)
loadURL = nil
}
}
}
class CustomWKWebViewController: UIViewController {
private func settingWebView() -> WKWebView {
let userScript = WKUserScript(source: source, injectionTime: .atDocumentStart, forMainFrameOnly: true)
let userContentController = WKUserContentController()
userContentController.add(self, name: "Login")
userContentController.add(self, name: "Other")
userContentController.add(self, name: “LD”)
userContentController.addUserScript(userScript)
let config = WKWebViewConfiguration()
config.userContentController = userContentController
webView = WKWebView(frame: .zero, configuration: config)
webView!.navigationDelegate = self
webView!.uiDelegate = self
webView!.scrollView.bounces = false
webView!.allowsBackForwardNavigationGestures = true
webView!.backgroundColor = .clear
webView!.scrollView.backgroundColor = .clear
if let request = getRequest() {
webView!.load(request)
}
return webView!
}
func reloadWebView(url: URL?) {
if let url = url, let webView = self.webView {
var requestForBlank = URLRequest(url: URL(string: "about:blank")!, cachePolicy: .reloadIgnoringLocalAndRemoteCacheData, timeoutInterval: 3)
requestForBlank.httpMethod = "POST"
var request = URLRequest(url: url, cachePolicy: .reloadIgnoringLocalAndRemoteCacheData, timeoutInterval: 3)
request.httpMethod = "POST"
webView.load(requestForBlank)
webView.load(request)//breakpoint always break here, but the view don't load request.
}
}
}
First you check if web url not nil, then also call the else part of if.
if let url = webview.url {
webview.reload()
} else {
webview.load(URLRequest(url: originalURL))
}

Swift video file captured doesn't exists in another viewcontroller

Captured a video in one viewcontroller and trying to preview it in another and upload it. Everything works fine till when I try the uploading where it gives me file doesn't exists
VideoRecorderViewController.swift
func finishRecording(outputFileURL: URL!) {
DispatchQueue.main.async { [unowned self] in
let path = outputFileURL.path
if FileManager.default.fileExists(atPath: path) {
//it comes here
}
let vc: VideoViewController? = self.storyboard?.instantiateViewController(withIdentifier: "VideoVC") as? VideoViewController
if let validVC: VideoViewController = vc {
validVC.videoURL = outputFileURL as NSURL?
self.navigationController?.pushViewController(validVC, animated: true)
}
}
}
VideoViewController.swift
var videoURL = NSURL(string: "")
#IBAction func btnSave(_ sender: Any) {
print (self.videoURL!)
// returns file:///private/var/mobile/Containers/Data/Application/228FAD74-B7C3-4838-8114-ED16D995FF9A/tmp/3B256E17-9875-4610-B8B3-348FBFAEC409.mov
print (self.videoURL!.path!)
//returns /private/var/mobile/Containers/Data/Application/228FAD74-B7C3-4838-8114-ED16D995FF9A/tmp/3B256E17-9875-4610-B8B3-348FBFAEC409.mov
let path = self.videoURL!.path!
if FileManager.default.fileExists(atPath: path) {
// "never comes"
}
}

Swift / UIWebView with xpath / css

I have an element of a website that I want to display within a UIWebView. The element has a unique ID for css as well as for xpath. Is it possible? How would I be able to do that? Help is very appreciated.
I usualy use this code:
let url : NSURL! = NSURL(string: "http://blablablabla.com")
webView.loadRequest(NSURLRequest(URL: url))
But I don't want to display the whole page. Only the element with that ID.
I assume you are using UIWebView, not the newer WKWebView. What you need is an HTML parser (I chose HTMLReader). After downloading the page content, extract the div you want and replace the page's body with the innerHTML of that div.
The code below gets the Did you know section on Wikipedia:
import HTMLReader
override func viewDidLoad() {
super.viewDidLoad()
loadHTML()
}
func loadHTML() {
let url = NSURL(string: "https://en.wikipedia.org/wiki/Main_Page")!
let request = NSURLRequest(URL: url)
let session = NSURLSession(configuration: NSURLSessionConfiguration.defaultSessionConfiguration())
let task = session.dataTaskWithRequest(request) { data, response, error in
guard error == nil else {
print(error!.localizedDescription)
return
}
guard let data = data else {
print("data is nil")
return
}
let html = HTMLDocument(data: data, contentTypeHeader: nil)
if let head = html.firstNodeMatchingSelector("head"),
didYouKnow = html.firstNodeMatchingSelector("#mp-dyk") {
let newHTML = "<html><head>\(head.innerHTML)</head><body>\(didYouKnow.innerHTML)</body></html>"
self.webView.loadHTMLString(newHTML, baseURL: url)
}
}
task.resume()
}
This is rather basic and is not 100% fool-proof though. See if it solves your problem.

Resources