code linking folder for local HTML, CSS, javascript app

Hello, I've been searching all over for this for days and I can't find the solution as I'm kind of illiterate with code so I have been reading and watching tutorials. Anyway, I have a webapp I created that is in HTML, CSS, and javascript. I have all the local files as I want it built-in to my xcode project. I am having trouble getting the code to work and this is what I have in the ViewController.swift All I am trying to do it make a simple app that can interact with my javascript using WKWebview tool.


This is what i have came up with and tried several things but no matter what I get a "SIGABRT" error. I think I am not telling it correctly where my files are located? Can someone please help? I have searched all over the web and apple documentation but since I don't know the code I don't really understand the language of what I am doing wrong. I tried looking at all the sub link apple documention and it shows you what to use but not really how to use it. So I feel like I am using it wrong...


import UIKit

import WebKit


class ViewController: UIViewController {


@IBOutlet weak var loadhtml: WKWebView!

override func viewDidLoad() {

super.viewDidLoad()

let webView = WKWebView()

let htmlPath = Bundle.main.path(forResource: "index", ofType: "html", inDirectory: "www")

let htmlUrl = URL(fileURLWithPath: htmlPath!)

let request = URLRequest(url: htmlUrl)

loadhtml.load(request)

webView.loadFileURL(htmlUrl, allowingReadAccessTo: htmlUrl)

view = webView

}


override func didReceiveMemoryWarning() {

super.didReceiveMemoryWarning()

}

// Do any additional setup after loading the view.

}


I have a "www" folder I added to the main file that has the index.html file in it along with a javascript file and also subolders with the images, CSS, etc..


I am getting frustrated trying to fix it.


Thank you in advance...

Answered by DTS Engineer in 374028022

You’re definitely approaching this from the right direction. Some suggestions:

  • Make sure that your

    www
    directory gets copied to your app correctly. To start, when you add it to the target, make sure to select “Create folder references” and not “Create groups”. Also, use the Finder to inspect the built app to confirm that everything is where you expect it to be.
  • Get your URL directly, rather than bouncing through a path, using:

    Bundle.main.url(forResource: "index", withExtension: "html", subdirectory: "www")

    .

  • Remove the

    URLRequest
    and everything that references it. You must use
    loadFileURL(_:allowingReadAccessTo:)
    .
  • Apropos that, pass the parent directory to the

    allowingReadAccessTo
    parameter:
    webView.loadFileURL(htmlUrl, allowingReadAccessTo: htmlUrl.deletingLastPathComponent())

    .

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"
Accepted Answer

You’re definitely approaching this from the right direction. Some suggestions:

  • Make sure that your

    www
    directory gets copied to your app correctly. To start, when you add it to the target, make sure to select “Create folder references” and not “Create groups”. Also, use the Finder to inspect the built app to confirm that everything is where you expect it to be.
  • Get your URL directly, rather than bouncing through a path, using:

    Bundle.main.url(forResource: "index", withExtension: "html", subdirectory: "www")

    .

  • Remove the

    URLRequest
    and everything that references it. You must use
    loadFileURL(_:allowingReadAccessTo:)
    .
  • Apropos that, pass the parent directory to the

    allowingReadAccessTo
    parameter:
    webView.loadFileURL(htmlUrl, allowingReadAccessTo: htmlUrl.deletingLastPathComponent())

    .

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Thank you so much for the help, I really appreciate it!


I tried what you asked and I also deleted and reinserted the "www" folder making sure the "create folder references" was checked, and also the "add to targets" was checked on the main app file. The html, css, javascript, etc. code works fine if I click on the "index.html" in the finder and open it in safari, works as expected.


I tried using:


let htmlPath = Bundle.main.path(forResource: "index", withExtension: "html", subDirectory: "www")


But it made me return it to:


let htmlPath = Bundle.main.path(forResource: "index", ofType: "html", inDirectory: "www")


I tried forcing the other one and the build failed.


I also deleted the URL request and added the code to allow access to the parent directory as you mentioned above with the "deletingLastPathComponent"


So this is where I am at now. The build succeeds, but I just get a white window and a SIGABRT error.


---------------------


import UIKit

import WebKit


class ViewController: UIViewController {


@IBOutlet weak var loadhtml: WKWebView!

override func viewDidLoad() {

super.viewDidLoad()

let webView = WKWebView()

let htmlPath = Bundle.main.path(forResource: "index", ofType: "html", inDirectory: "www")

let htmlUrl = URL(fileURLWithPath: htmlPath!)

webView.loadFileURL(htmlUrl, allowingReadAccessTo: htmlUrl.deletingLastPathComponent())

view = webView

}


override func didReceiveMemoryWarning() {

super.didReceiveMemoryWarning()

}

// Do any additional setup after loading the view.



}

-------------------------



Is there something else wrong in the code yet?


I have tried so many things I feel lost and don't know what to try next.


Thank you again, I really appreciate it.

Combine these lines:

let htmlPath = Bundle.main.path(forResource: "index", ofType: "html", inDirectory: "www")
let htmlUrl = URL(fileURLWithPath: htmlPath!)

into this:

let htmlURL = Bundle.main.url(forResource: "index", withExtension: "html", subdirectory: "www")!

There’s two reasons for this:

  • Try to prevent optionals from ‘escaping’. In this case, if you’re going to force unwrap something, force unwrap it as soon as possible.

  • When references files, work with file URLs not path strings.

As to why you’re getting a

SIGABRT
, it’s hard to say, but I have a couple more debugging suggestions:
  • Look at the built app to make sure that things are laid out like you expect. To do this:

    1. In Xcode, choose View > Navigators > Show Project Navigator.

    2. Locate the app in the Products group on the left.

    3. Control click on it and choose Show in Finder.

    4. In the Finder, control click on the app and choose Show Package Contents.

    5. Make sure your

      www
      directory is embedded within your app, and it has the expected contents.

    If not, post a summary of what you see and we can take things from there.

  • If that doesn’t reveal anything, run the app from the Home screen, which should trigger a crash. Then grab the crash report and post it here. Use the

    <>
    button to format the crash report as code.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Thnak you very much again, it works!


When you had me check the app package contents, the www folder wasn't there.


I made a mistake when I was trying different things to fix it, and I copied the whole folder and opened the new project. Well, I don't think it was referencing the right project anymore. So although we fixed the code it still wasn't finding the files.


So I opened a new fresh project in an empy folder, and I created the new app with this (I took your advice and shortened the code)



-------------------------

import UIKit

import WebKit


class ViewController: UIViewController {


@IBOutlet weak var loadhtml: WKWebView!

override func viewDidLoad() {

super.viewDidLoad()


let webView = WKWebView()

let htmlURL = Bundle.main.url(forResource: "index", withExtension: "html", subdirectory: "www")!

webView.loadFileURL(htmlURL, allowingReadAccessTo: htmlURL.deletingLastPathComponent())

view = webView

}

}

-------------------------


The app works now! Thank you so much for the help, I really appreciate it.


I do have two questions though.


1 - There is a web link within my app, and it does not work, you click on it in the simulator and nothing happens. Do I need to add code for this to work? It should open in Safari?


2 - I have a slider to change the font size for a tablet vs a phone, etc. It works great in the local html & css in Safari but it doesn't work in the app. Is there something i need to add to allow that to change in the app? The slider is there and works but you slide it and nothing happens.


Thanks again so much!

There is a web link within my app, and it does not work, you click on it in the simulator and nothing happens. Do I need to add code for this to work? It should open in Safari?

WKWebView
will never pass links to Safari. It’s built-in behaviour is to either follow the link internally or fail. If you want to pass a URL to Safari, you should implement the web view’s navigation delegate, look for it navigating to that URL, and then call
open(_:options:completionHandler:)
on that. Here’s some documentation links:

I have a slider to change the font size for a tablet vs a phone, etc. It works great in the local html & css in Safari but it doesn't work in the app. Is there something i need to add to allow that to change in the app?

I don’t have any input on this issue, because it’s about the content of the web view rather than the web view API, and I have little experience with web content. I recommend that you ask this question someplace where you’re more likely to connect up with web content experts, like the Safari and Web area of DevForums.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Thank you Quinn, I will look into this navigation delegate and see if i can make sense of it. You've been a big help. I'll get back to you with my results.


As for the font size slider, it is embedded in the html and CSS, which works fine in Safari, Chrome, Explorer, etc. It isn't until I put it in xcode and make an app out of it that it stops working, so I feel like it is something to do with a limitation of webview? I was wondering if there is something i can do to "allow" it to function again?


Thank you,


Heath

I was wondering if there is something i can do to "allow" it to function again?

Yeah, sorry, no idea.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

So I have been trying several different code methods I found using your initial ideas and I have gotten the build to run in the simulator with this code in the view controller. However, no matter what I do it seems it either fails or succeeds but doesn't fix the broken links. I also tried putting it in the app delegate and moving it above and below the } view did load brackets, but it didn't seem to make a difference.


I tried running the code with WKWebview instead of UIWebview and it kept failing with errors. Maybe i shouldn't be mixing in this UIWebviewDelegate, I don't know. Please advise.


What am I missing?


----------------------


import UIKit

import WebKit


class ViewController: UIViewController, WKNavigationDelegate, UIWebViewDelegate {


@IBOutlet weak var loadhtml: WKWebView!

override func viewDidLoad() {

super.viewDidLoad()

let webView = WKWebView()

let htmlURL = Bundle.main.url(forResource: "index", withExtension: "html", subdirectory: "www")!

webView.loadFileURL(htmlURL, allowingReadAccessTo: htmlURL.deletingLastPathComponent())

view = webView

}


func webView(_: UIWebView, shouldStartLoadWith: URLRequest, navigationType: UIWebView.NavigationType) -> Bool {

if navigationType == UIWebView.NavigationType.linkClicked {

UIApplication.shared.open(shouldStartLoadWith.url!, options: [:], completionHandler: nil)

return false

}

return true

}


}


-----------------------


Thanks again for all your help...

Also, as I spend hours trying to fix the problem, it's possibly I may be attemping to fix the wrong problem first. My links work fine in the html in safari, etc. However, the links embedded in the webview do absoultely nothing in the app. They don't open in the app either, I'm not even sure you can click on it. Is there something I need to enable in xcode to allow it to access the network, etc? I'll keep searching in the meantime...

First up, do not use

UIWebView
. It’s been officially deprecated, and for good reason.

There’s a couple of problems with your code:

  • Your view controller has adopted the

    WKNavigationDelegate
    protocol but is not actually set as the navigation delegate on the web view. You need this line:
    webView.navigationDelegate = self

    immediately after creating the web view.

  • Your view controller has implemented a

    UIWebViewDelegate
    delegate method rather than the
    WKNavigationDelegate
    one. To fix this:
    1. Remove the conformance to

      UIWebViewDelegate
      .
    2. Change that method to the one I referenced earlier,

      webView(_:decidePolicyFor:decisionHandler:)
      . This method uses a decision handler callback, so you’ll also need to slightly tweak the code.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Well, I have this after a lot of reading and it still doesn't work. I must still be missing something...


I substituted "xyz.com" for my url just for illustration purposes for anyone reading this in the future.


You can likely see I am very limited in understanding the code. I think most of the instructions assume you know what you are doing so they leave most of the details out and it makes it hard to understand what goes where.


Suggestions?


----------------------


import UIKit

import WebKit


class ViewController: UIViewController,WKNavigationDelegate {


@IBOutlet weak var loadhtml: WKWebView!


override func viewDidLoad() {

super.viewDidLoad()

let webView = WKWebView()

webView.navigationDelegate = self

let htmlURL = Bundle.main.url(forResource: "index", withExtension: "html", subdirectory: "www")!

webView.loadFileURL(htmlURL, allowingReadAccessTo: htmlURL.deletingLastPathComponent())

view = webView

func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {

if let host = navigationAction.request.url?.host {

if host.contains("xyz.com") {

decisionHandler(.allow)

return

}

}

decisionHandler(.cancel)

}

}



}

----------------------


Thanks again for all your help...

It looks like you’ve implementing your web view navigation delegate callback as a local function inside your

viewDidLoad
method. This is easy to see once you remove all the details from your code and just focus on the structure:
class ViewController: UIViewController, WKNavigationDelegate {

    override func viewDidLoad() {
        …

        func webView(… decidePolicyFor …)  {
            …
        }
    }
}

What you need is this code to be a method in your

ViewController
class, that is, a peer of
viewDidLoad
. Again, with all the details removed:
class ViewController: UIViewController, WKNavigationDelegate {

    override func viewDidLoad() {
        …
    }

    func webView(… decidePolicyFor …)  {
        …
    }
}

Unfortunately the compiler isn’t currently able to warn you about this because all of the methods in

WKNavigationDelegate
are optional. However, this is not the first time I’ve seen folks get tripped up by this, so I’ve filed a bug requesting that the compiler be smarter about this (r. 54339239).

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Thanks again for all your help Quinn, I am now at this point, at first it was blocking the webview itself from working, but I moved the self navigation callout line below the view did Load and down below, and now the app works again, but it still doesn't allow the link to open? I tried putting the self navigation callout between but then it failed saying it needed a declaration.


I understand what you did now, but I still can't get the links to open in the app?


----------------------------


import UIKit

import WebKit


class ViewController: UIViewController,WKNavigationDelegate {


@IBOutlet weak var loadhtml: WKWebView!


override func viewDidLoad(){

super.viewDidLoad()

let webView = WKWebView()

let htmlURL = Bundle.main.url(forResource: "index", withExtension: "html", subdirectory: "www")!

webView.loadFileURL(htmlURL, allowingReadAccessTo: htmlURL.deletingLastPathComponent())

view = webView

}

func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {

webView.navigationDelegate = self

if let host = navigationAction.request.url?.host{

if host.contains("innovateengineering.pro"){

decisionHandler(.allow)

return

}

}

decisionHandler(.cancel)

}

}


--------------------------------

code linking folder for local HTML, CSS, javascript app
 
 
Q