Search code examples
iosswiftwkwebviewhttpservergcdwebserver

Access local files in WKWebView using JavaScript


I have an iOS app which part of logic is written in JavaScript. I've created a WKWebView where I load my initial .js file, but when executed, it needs to read from other files from my local resources. The problem is I'm missing a concept of how do I achieve that.

I've tried loading each separate file one after another in Swift into the webView but it's too many files to load by hand.
I though, maybe there is a http server for Swift that will have an access to project files. And I found solutions like this or this.
An approach looks great but even if I do so, I still can't access files and folders from my Xcode project structure. I've created a basic http server and also a DAV server, added GET handlers, etc.

Maybe I'm doing something wrong with setting it up but at the end when I create an object of http server, I can still access it from my webView at http://192.168.0.11:8080 so for sure it's initialized properly and working.


Solution

  • Answering my question so it helps someone in the future. I've used at the end this library. And it looks like there was some configuration missing so the server serves all the pages and files dynamically. My code is:

    guard let websitePath = Bundle.main.path(forResource: "myFolderNameInProjectStructure", ofType: nil) else { return }
    let httpServer = GCDWebServer()
    httpServer.addGETHandler(forBasePath: "/", directoryPath: websitePath, indexFilename: nil, cacheAge: 3600, allowRangeRequests: true)
    httpServer.addHandler(forMethod: "GET", pathRegex: "/.*\\.html", request: GCDWebServerRequest.self) { (request) in
        return GCDWebServerDataResponse(htmlTemplate: websitePath + request.path, variables: ["variable": "value"])
    }
    httpServer.start(withPort: 8080, bonjourName: "MC Local Server")
    

    When this configuration is done and the server is running on port of your choice (mine is 8080), you simply open up your embedded browser inside the app (e.g. WKWebView) and load

    let url = URL(string: "http://localhost:8080/index.html")!
    webView.load(URLRequest(url: url))
    

    If you simply always want to run index.html when connecting to / of the http server, you can add this configuration before httpServer.start() method:

    httpServer.addHandler(forMethod: "GET", path: "/", request: GCDWebServerRequest.self) { (request) in
        return GCDWebServerResponse(redirect: URL(string: "index.html")!, permanent: true)
    }
    

    And now in webView just connect to http://localhost:8080 and the file you have given as a GCDWebServerResponse will load.