Swift4 app crashes when loading local HTML [duplicate] - ios

This question already has answers here:
WKWebView does load resources from local document folder
(8 answers)
Closed 5 years ago.
While working on a web app for weeks, I used a external URL in my (WKWebView) web view. Now I'm moving towards production I want to embed the webapp and load a local webpage.
I simply moved from
let url = URL(string: "http://hidden-url.com/")
self.webView!.load(URLRequest(url: url!))
To
let url = URL(string: Bundle.main.path(forResource: "index_prod", ofType: "html")!)
self.webView!.load(URLRequest(url: url!))
But this causes my app to crash. I'm sure the file is loaded correctly and a print before, in-between and after the lines will appear in the console.
The error: Thread 1: EXC_BAD_ACCESS (code=1, address=0x10)

You need to load the string content from the file, use contentsOfFile method to get the string and use loadHTMLString method of webview, print the error or create some enum which shows the error
enum WebError: Swift.Error {
case fileNotFound(name: String)
case parsing(contentsOfFile: String)
}
guard let url = Bundle.main.path(forResource: "index_prod", ofType: "html") else {
throw WebError.fileNotFound(name: file) // throw file not found error
}
do {
let html = try String(contentsOfFile: url)
self.webView.loadHTMLString(html, baseURL: Bundle.main.bundleURL)
} catch {
throw WebError.parsingError(contentsOfFile: file)
}

Related

In webView leads to crash and UI unresponsiveness

I have added a WebView to load HTML and the baseUrl method. But it leads to crashing the app and showing a warning
This method should not be called on the main thread as it may lead to
UI unresponsiveness.
//load HTML
let htmlPath = Bundle.main.path(forResource: "index", ofType: "html")
let folderPath = Bundle.main.bundlePath
let baseUrl = URL(fileURLWithPath: folderPath, isDirectory: true)
do {
let htmlString = try NSString(contentsOfFile: htmlPath!, encoding: String.Encoding.utf8.rawValue)
self.webView.loadHTMLString(htmlString as String, baseURL: URL(string: newBaseURL))
} catch {
// catch error
print(error.localizedDescription)
}
I have called this piece of code in viewDidLoad(). Also it has been added in dispatch queue. Any help is much appreciated.
Call loadHTMLString from the main thread.
DispatchQueue.main.async {
self.webView.loadHTMLString(htmlString as String, baseURL: URL(string: newBaseURL))
}
You have 2 issues and one of them is a bug address by Apple itself -
a. Warning of WKWebkit on main thread - This has been covered by one of Apple's engineers where he goes into detail on this thread. Short answer - Its a bug and Apple is working on it in further releases. Now according to them this is supposed to be a warning and it shouldnt have any issues with the API itself.
b. The Webview is unresponsive. As explained above the warning shouldn't be causing an issue with anything API related. So for this I would suggest you to check the HTML you are trying to render separately. If that works fine, maybe try to launch it in a separate device, or even simulator. Try to make the HTML render on a consistent basis in other environment(device / simulator). I think either the device you are using has an older OS.
Please try to test the same HTML on separate devices / simulators and share your results here.
To fix this issue, you can move the code that loads the HTML string and sets the baseURL to a background thread using DispatchQueue. This will allow the main thread to continue running and handling user input, preventing the app from becoming unresponsive. Checkout the below code:
DispatchQueue.global(qos: .userInitiated).async {
let htmlPath = Bundle.main.path(forResource: "index", ofType: "html")
let folderPath = Bundle.main.bundlePath
let baseUrl = URL(fileURLWithPath: folderPath, isDirectory: true)
do {
let htmlString = try NSString(contentsOfFile: htmlPath!, encoding: String.Encoding.utf8.rawValue)
DispatchQueue.main.async {
self.webView.loadHTMLString(htmlString as String, baseURL: URL(string: newBaseURL))
}
} catch {
// catch error
print(error.localizedDescription)
}
}

Unable to load a pdf file that has been created

I have saved and opened a PDF file on my view controller, and then I save the array of PDFs to the system data. I then pull my array from the data and use the string of the location in the new view controller. However when I attempt to load the file at said directory it fails to appear in the WebView, even though I was able to load it from the same directory on the first ViewController.
How can I get it to open after the app has been closed?
Here is how I save and open the PDF the first time:
func generatePreview() {
let A4paperSize = CGSize(width: 595, height: 842)
let pdf = SimplePDF(pageSize: A4paperSize, pageMargin: 20.0)
createFirstPage(x: pdf)
pdf.beginNewPage()
addAreas(x: pdf)
//add disclamer and like dress the pdf up
let pdfData = pdf.generatePDFdata()
let resourceDocPath = (FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)).last! as URL
let pdfNameFromUrl = "Survey-\(finalOverview.name).pdf"
let actualPath = resourceDocPath.appendingPathComponent(pdfNameFromUrl)
do {
try pdfData.write(to: actualPath, options: .atomic)
print("pdf successfully saved!")
} catch {
print("Pdf could not be saved")
}
let request = URLRequest(url: actualPath)
pdfPreview.load(request)
let pdfObj = pdfArray(fileTitle: finalOverview.name, fileName: actualPath)
//pdfView.GlobalVariable.myPDFs.append(pdfObj)
savePDF(x: pdfObj)
}
I made the mentioned changes but still no luck
My issue was when I was creating the string the second time, the optional was not wrapped. So when I unwrapped it the code worked as intended.

WebView (not WKWebView) calling Localized HTML file

A Mac app requires that a HTML file be called in a WebView (the legacy type, not the newer WKWebView) in a localized form to present the user with some content.
As I side note, I realize that WebView should not be used today, and WKWebView is preferred, however this is a legacy app that currently needs support.
I've used a similar method for the iOS version, however it does not seem to be working. The HTML files are simply called "Term.HTML" and are placed in each localization folder alongside the localized string and all other localized content. This is the code I tried to use:
NSString *htmlFile = [[NSBundle mainBundle] pathForResource:NSLocalizedString(#"fileTerm", nil) ofType:#"html"];
htmlString = [NSString stringWithContentsOfFile:htmlFile encoding:NSUTF8StringEncoding error:nil];
[termsView takeStringURLFrom:htmlString];
Where my localized strings file each contain a line that says:
"fileTerm" = "Term";
This is what links the declaration of the first line to the actual file. It works in iOS. However, when running the app and the view containing the WebView attempt to the run, XCode will automatically create a breakpoint on the third line when I actually attempt to give the HTML file to "termsView" which is my WebView. After skipping this breakpoint, and forcing the app to run, the whole view containing the WebView will simply not appear. I would be thankful if anyone knew why this was or if there was a better way to do this? Thank you everyone!
may be someone needs in SWift: I solved this problem with saving 3 html file for every language, and then in ViewController class checked current app language. And called up the html file for current language
func loadHtmlFile() {
let preferredLanguage = NSLocale.preferredLanguages[0]
if preferredLanguage == "kz" {
let url = Bundle.main.url(forResource: "aboutUs_kz", withExtension:"html")
let request = URLRequest(url: url!)
webView.load(request)
}
if preferredLanguage == "ru" {
let url = Bundle.main.url(forResource: "aboutUs_ru", withExtension:"html")
let request = URLRequest(url: url!)
webView.load(request)
}
if preferredLanguage == "en" {
let url = Bundle.main.url(forResource: "aboutUs_en", withExtension:"html")
let request = URLRequest(url: url!)
webView.load(request)
}
}
in viewDidLoad()
override func viewDidLoad() {
super.viewDidLoad()
loadHtmlFile()
}

Open some items in UIWebView, and others in external browser

I'm creating a html5 app, embed in UIWebView. I have delegate webview to controller, and on shouldStartLoadWithRequest, I'm looking for url pattern to open or not on external browser.
It's work perfect!
But when phone has no connection, I'm loading local html file. Because shouldStartLoadWithRequest return FALSE on first request, offline.html not loading
Anyone has do that?
Try this immediately after set path :
do {
let path = NSBundle.mainBundle().pathForResource("offline", ofType: "html", inDirectory:"offline")
let string = try String(contentsOfFile: path!, encoding:NSUTF8StringEncoding)
webView.loadHTMLString(string, baseURL: NSURL(string: "http://"))
} catch {
print(error)
}
or
let url = NSURL(fileURLWithPath:NSBundle.mainBundle().pathForResource("offline", ofType:"html", inDirectory: "offline")!)
let request = NSURLRequest(URL: url);
webView.loadRequest(request);
I tried it and it works.
Make sure your "offline" directory is a folder (BLUE) and not a group (YELLOW).
Hope this help.
I found the problem. I'm not triggering error -1003 (no host found)! removing switch work perfectly!

IOS/Swift: Open PDF from a local path into a Web View

I previously used below code to open up a dummy PDF, just for testing purpose, and now for the actual project i have to load a pdf based on the table cell clicked that will give the exact path of the pdf at some local path.
self.termsPath = NSBundle.mainBundle().pathForResource("DemoForm", ofType: "pdf")!
let url = NSURL(fileURLWithPath: termsPath!)
let pdfRequest = NSURLRequest(URL: url!)
pdfWebView.loadRequest(pdfRequest)
pdfWebView.scalesPageToFit = true
Now i have thisvariable docPath that will be passed from the prepareforSegue when table cell is clicked, i tried to use this variable in place of DemoForm but it gives below error
Thread 1: EXC_BAD_INSTRUCTION (code=EXC_1386_INVOP, subcode=0x0
Where i'm i going wrong here? Can anyone help me.Thanks
EDIT: By the way my docPath refers to something like ".../.../.../.../Referral.pdf"

Resources