Javascript 带有文件url的WKWebView xmlhttprequest

Javascript 带有文件url的WKWebView xmlhttprequest,javascript,ios,ajax,wkwebview,Javascript,Ios,Ajax,Wkwebview,我正在使用app documents文件夹中的本地HTMLs从UIWebView迁移到WKWebView。 我可以加载包含所有css和js文件的索引页面,但是由于允许的访问来源,每个ajax调用(xmlhttprequest)都会失败 我不想在我的应用程序中使用Web服务器,因为我认为它会过大。我怎样才能做到这一点?该应用程序是一个简单的HTML5应用程序,用于内部应用程序。设备无法联机,或者任何安全功能都可能被完全禁用。对于那些通过此功能找到此主题的用户: 这不是正式关闭WKWebView中的

我正在使用app documents文件夹中的本地HTMLs从UIWebView迁移到WKWebView。 我可以加载包含所有css和js文件的索引页面,但是由于允许的访问来源,每个ajax调用(xmlhttprequest)都会失败


我不想在我的应用程序中使用Web服务器,因为我认为它会过大。我怎样才能做到这一点?该应用程序是一个简单的HTML5应用程序,用于内部应用程序。设备无法联机,或者任何安全功能都可能被完全禁用。

对于那些通过此功能找到此主题的用户:

这不是正式关闭WKWebView中的安全性,但我们可以使用私有API来实现这一点,就像这家伙在Cordova项目中所做的那样:

线索是为WebView创建配置并设置allowFileAccessFromFileURLs属性

WKWebViewConfiguration* configuration = originalImpSend(_self, selector, settings);

// allow access to file api
@try {
    [configuration.preferences setValue:@TRUE forKey:@"allowFileAccessFromFileURLs"];
}
@catch (NSException *exception) {}

@try {
    [configuration setValue:@TRUE forKey:@"allowUniversalAccessFromFileURLs"];
}
@catch (NSException *exception) {}

return configuration;

但正如我提到的,这是私有API,这可能是在苹果的应用程序审查中拒绝你的应用程序的一个原因。如果您想在App Store中发布应用程序,请考虑运行一些轻量级HTTP服务器,而不是违反Web视图的整体安全性。示例:。

这解决了我的问题:

let config = WKWebViewConfiguration()
config.userContentController = contentController
config.preferences.setValue(true, forKey: "allowFileAccessFromFileURLs")
webView = WKWebView(frame: .zero, configuration: config)
webView.uiDelegate = self
webView.navigationDelegate = self
view = webView

因此,当我第一次尝试它时,accepted对我不起作用(当时我做得不对),它强烈建议不要做的关于()的bug。我的解决方案是实现一个自定义url方案,并使用它加载所有文件。看起来像这样

首先创建附加了url方案的WKWebView(必须自己创建WKWebView,不能在情节提要上创建)

然后实现处理程序

import Foundation
import WebKit
import MobileCoreServices

class PrayerAssetHandler: NSObject, WKURLSchemeHandler {

    func webView(_ webView: WKWebView, start urlSchemeTask: WKURLSchemeTask) {
        let url = urlSchemeTask.request.url!

        let pathArr = url.path.components(separatedBy: ".")
        let forResource: String = pathArr[0]
        let ofType: String? = pathArr.count > 1 ? pathArr[1] : nil

        let bundlePath = Bundle.main.path(forResource: "data_sub_folder" + forResource, ofType: ofType)

        let fileExtension: CFString = ofType! as CFString
        guard
            let extUTI = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension,
                                fileExtension, nil)?.takeUnretainedValue()
        else { return }

        guard
            let mimeUTI: NSString = UTTypeCopyPreferredTagWithClass(extUTI,
                                kUTTagClassMIMEType)?.takeRetainedValue()
        else { return }

        let mimeType: String = mimeUTI as String

        do {
            let data: Data = try NSData(contentsOfFile: bundlePath!) as Data

            //Create a NSURLResponse with the correct mimetype.
            let urlResponse = URLResponse(url: url, mimeType: mimeType,
                                          expectedContentLength: data.count, textEncodingName: "utf8")
            urlSchemeTask.didReceive(urlResponse)
            urlSchemeTask.didReceive(data)
            urlSchemeTask.didFinish()
        }  catch _ as NSError {
            return
        }

    }

    func webView(_ webView: WKWebView, stop urlSchemeTask: WKURLSchemeTask) {
    }
}

哇,谢谢你!经过这段时间,我终于可以从UIWebView迁移到WKWebView了。你的解决方案对我来说很好。谢谢你的例子!这里有两件事并不明显:要加载带有自定义方案的页面,您必须提供自己的navigationDelegate来确认您的请求。还要记住,
NSResponse
没有状态代码,会导致XMLHttpUrlRequests失败(和/或像axios这样的库)。改用
NSHttpUrlResponse
import Foundation
import WebKit
import MobileCoreServices

class PrayerAssetHandler: NSObject, WKURLSchemeHandler {

    func webView(_ webView: WKWebView, start urlSchemeTask: WKURLSchemeTask) {
        let url = urlSchemeTask.request.url!

        let pathArr = url.path.components(separatedBy: ".")
        let forResource: String = pathArr[0]
        let ofType: String? = pathArr.count > 1 ? pathArr[1] : nil

        let bundlePath = Bundle.main.path(forResource: "data_sub_folder" + forResource, ofType: ofType)

        let fileExtension: CFString = ofType! as CFString
        guard
            let extUTI = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension,
                                fileExtension, nil)?.takeUnretainedValue()
        else { return }

        guard
            let mimeUTI: NSString = UTTypeCopyPreferredTagWithClass(extUTI,
                                kUTTagClassMIMEType)?.takeRetainedValue()
        else { return }

        let mimeType: String = mimeUTI as String

        do {
            let data: Data = try NSData(contentsOfFile: bundlePath!) as Data

            //Create a NSURLResponse with the correct mimetype.
            let urlResponse = URLResponse(url: url, mimeType: mimeType,
                                          expectedContentLength: data.count, textEncodingName: "utf8")
            urlSchemeTask.didReceive(urlResponse)
            urlSchemeTask.didReceive(data)
            urlSchemeTask.didFinish()
        }  catch _ as NSError {
            return
        }

    }

    func webView(_ webView: WKWebView, stop urlSchemeTask: WKURLSchemeTask) {
    }
}