13 Replies
      Latest reply on Aug 15, 2019 7:35 AM by folkenheath
      folkenheath Level 1 Level 1 (0 points)

        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...

        • Re: code linking folder for local HTML, CSS, javascript app
          eskimo Apple Staff Apple Staff (11,655 points)

          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"

            • Re: code linking folder for local HTML, CSS, javascript app
              folkenheath Level 1 Level 1 (0 points)

              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.

                • Re: code linking folder for local HTML, CSS, javascript app
                  eskimo Apple Staff Apple Staff (11,655 points)

                  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"

                    • Re: code linking folder for local HTML, CSS, javascript app
                      folkenheath Level 1 Level 1 (0 points)

                      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! 

                        • Re: code linking folder for local HTML, CSS, javascript app
                          eskimo Apple Staff Apple Staff (11,655 points)

                          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"

                            • Re: code linking folder for local HTML, CSS, javascript app
                              folkenheath Level 1 Level 1 (0 points)

                              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

                              • Re: code linking folder for local HTML, CSS, javascript app
                                folkenheath Level 1 Level 1 (0 points)

                                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...

                                  • Re: code linking folder for local HTML, CSS, javascript app
                                    folkenheath Level 1 Level 1 (0 points)

                                    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...

                                    • Re: code linking folder for local HTML, CSS, javascript app
                                      eskimo Apple Staff Apple Staff (11,655 points)

                                      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"

                                        • Re: code linking folder for local HTML, CSS, javascript app
                                          folkenheath Level 1 Level 1 (0 points)

                                          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...

                                            • Re: code linking folder for local HTML, CSS, javascript app
                                              eskimo Apple Staff Apple Staff (11,655 points)

                                              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"

                                                • Re: code linking folder for local HTML, CSS, javascript app
                                                  folkenheath Level 1 Level 1 (0 points)

                                                  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)

                                                      }

                                                  }

                                                   

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