WKWebView不加载的iOS 8下的本地文件WKWebView不加载的iOS 8下的本地文件(W

2019-05-09 07:42发布

对于以前的iOS测试版8,负荷(束)本地web应用程序,它两个工作正常UIWebViewWKWebView ,我甚至移植使用新的网页游戏WKWebView API。

var url = NSURL(fileURLWithPath:NSBundle.mainBundle().pathForResource("car", ofType:"html"))

webView = WKWebView(frame:view.frame)
webView!.loadRequest(NSURLRequest(URL:url))

view.addSubview(webView)

但在测试4,我刚刚得到一个空白屏幕( UIWebView仍然有效),貌似没有什么是加载或执行。 我看到在日志中的错误:

无法创建一个沙箱扩展/

任何帮助引导我正确的方向? 谢谢!

Answer 1:

他们终于解决了这个错误! 现在我们可以使用-[WKWebView loadFileURL:allowingReadAccessToURL:] 。 显然,修复是值得几秒钟在WWDC 2015年视频504引入的Safari浏览器

对于iOS8上〜iOS10(SWIFT 3)

由于丹Fabulish的回答状态,这是这显然不被很快解决任何时候 WKWebView的一个错误,因为他说有一个变通:)

我回答,只是因为我想在这里展示的变通。 在所示IMO代码https://github.com/shazron/WKWebViewFIleUrlTest充满无关的细节大多数人可能不感兴趣的内容。

的解决办法是20行代码,错误处理和意见包括,不需要服务器的:)

func fileURLForBuggyWKWebView8(fileURL: URL) throws -> URL {
    // Some safety checks
    if !fileURL.isFileURL {
        throw NSError(
            domain: "BuggyWKWebViewDomain",
            code: 1001,
            userInfo: [NSLocalizedDescriptionKey: NSLocalizedString("URL must be a file URL.", comment:"")])
    }
    try! fileURL.checkResourceIsReachable()

    // Create "/temp/www" directory
    let fm = FileManager.default
    let tmpDirURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent("www")
    try! fm.createDirectory(at: tmpDirURL, withIntermediateDirectories: true, attributes: nil)

    // Now copy given file to the temp directory
    let dstURL = tmpDirURL.appendingPathComponent(fileURL.lastPathComponent)
    let _ = try? fm.removeItem(at: dstURL)
    try! fm.copyItem(at: fileURL, to: dstURL)

    // Files in "/temp/www" load flawlesly :)
    return dstURL
}

并且可以作为:

override func viewDidLoad() {
    super.viewDidLoad()
    var fileURL = URL(fileURLWithPath: Bundle.main.path(forResource:"file", ofType: "pdf")!)

    if #available(iOS 9.0, *) {
        // iOS9 and above. One year later things are OK.
        webView.loadFileURL(fileURL, allowingReadAccessTo: fileURL)
    } else {
        // iOS8. Things can (sometimes) be workaround-ed
        //   Brave people can do just this
        //   fileURL = try! pathForBuggyWKWebView8(fileURL: fileURL)
        //   webView.load(URLRequest(url: fileURL))
        do {
            fileURL = try fileURLForBuggyWKWebView8(fileURL: fileURL)
            webView.load(URLRequest(url: fileURL))
        } catch let error as NSError {
            print("Error: " + error.debugDescription)
        }
    }
}


Answer 2:

通过其网址:WKWebView无法加载从文件内容loadRequest:方法。 http://www.openradar.me/18039024

您可以通过加载内容loadHTMLString:但如果你是基本URL文件:URL,那么它仍然无法工作。

iOS版9有一个新的API,将你想要做什么, [WKWebView loadFileURL:allowingReadAccessToURL:]

有针对iOS 8一种变通方法 ,通过shazron在这里Objective-C的证明https://github.com/shazron/WKWebViewFIleUrlTest到的文件复制到/tmp/www并从那里加载它们 。

如果你在工作斯威夫特,你可以尝试nachos4d的样品来代替。 (它也比shazron的样品要短得多,因此,如果您遇到shazron代码的麻烦,给一个尝试吧。)



Answer 3:

iOS 9如何使用[::allowingReadAccessToURL WKWebView loadFileURL]的例子。

当您移动Web文件夹到项目中,选择“创建文件夹引用”

然后使用代码是这样的(SWIFT 2):

if let filePath = NSBundle.mainBundle().resourcePath?.stringByAppendingString("/WebApp/index.html"){
  let url = NSURL(fileURLWithPath: filePath)
  if let webAppPath = NSBundle.mainBundle().resourcePath?.stringByAppendingString("/WebApp") {
    let webAppUrl = NSURL(fileURLWithPath: webAppPath, isDirectory: true)
    webView.loadFileURL(url, allowingReadAccessToURL: webAppUrl)
  }
}

在HTML文件中使用的文件路径是这样

<link href="bootstrap/css/bootstrap.min.css" rel="stylesheet">

不喜欢这

<link href="/bootstrap/css/bootstrap.min.css" rel="stylesheet">

被移动到Xcode项目目录的一个例子。



Answer 4:

临时解决方法:我使用GCDWebServer ,通过GuidoMB的建议。

我第一次发现我的捆绑的“www /”文件夹的路径(其中包含一个“的index.html”):

NSString *docRoot = [[NSBundle mainBundle] pathForResource:@"index" ofType:@"html" inDirectory:@"www"].stringByDeletingLastPathComponent;

......然后启动它,就像这样:

_webServer = [[GCDWebServer alloc] init];
[_webServer addGETHandlerForBasePath:@"/" directoryPath:docRoot indexFilename:@"index.html" cacheAge:3600 allowRangeRequests:YES];
[_webServer startWithPort:port bonjourName:nil];

要停止它:

[_webServer stop];
_webServer = nil;

业绩显示正常,甚至在iPad 2。


我做了应用程序进入后台后发现崩溃,所以我停止它applicationDidEnterBackground:applicationWillTerminate: ; 我启动/重新启动它的application:didFinishLaunching...applicationWillEnterForeground:



Answer 5:

除了丹Fabulich提到的解决方案, XWebView是另一种解决办法。 [WKWebView loadFileURL:allowingReadAccessToURL:]是通过扩展实现 。



Answer 6:

[configuration.preferences setValue:@"TRUE" forKey:@"allowFileAccessFromFileURLs"];

这解决了这个问题对我来说的iOS 8.0+ dev.apple.com

也这似乎只是正常工作太...

NSString* FILE_PATH = [[[NSBundle mainBundle] resourcePath]
                       stringByAppendingPathComponent:@"htmlapp/FILE"];
[self.webView
    loadFileURL: [NSURL fileURLWithPath:productURL]
    allowingReadAccessToURL: [NSURL fileURLWithPath:FILE_PATH]
];


Answer 7:

我不能评论,所以我很张贴这作为一个单独的答案。

这是一个Objective-C版本nacho4d的解决方案 。 到目前为止,我见过的最好的解决方法。

- (NSString *)pathForWKWebViewSandboxBugWithOriginalPath:(NSString *)filePath
{
    NSFileManager *manager = [NSFileManager defaultManager];
    NSString *tempPath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"www"];
    NSError *error = nil;

    if (![manager createDirectoryAtPath:tempPath withIntermediateDirectories:YES attributes:nil error:&error]) {
        NSLog(@"Could not create www directory. Error: %@", error);

        return nil;
    }

    NSString *destPath = [tempPath stringByAppendingPathComponent:filePath.lastPathComponent];

    if (![manager fileExistsAtPath:destPath]) {
        if (![manager copyItemAtPath:filePath toPath:destPath error:&error]) {
            NSLog(@"Couldn't copy file to /tmp/www. Error: %@", error);

            return nil;
        }
    }

    return destPath;
}


Answer 8:

在您尝试在一个较大的HTML串状的中间显示本地图像的情况下: <img src="file://...">它仍然没有出现在设备,所以我加载图像文件成的NSData,并能够通过与该数据本身替换SRC字符串来显示它。 示例代码,以帮助建立HTML字符串加载到WKWebView,其中结果是什么将取代什么是SRC的=“”引号内:

迅速:

let pathURL = NSURL.fileURLWithPath(attachmentFilePath)
guard let path = pathURL.path else {
    return // throw error
}
guard let data = NSFileManager.defaultManager().contentsAtPath(path) else {
    return // throw error
}

let image = UIImage.init(data: data)
let base64String = data.base64EncodedStringWithOptions(.Encoding64CharacterLineLength)
result += "data:image/" + attachmentType + "base64," + base64String

var widthHeightString = "\""
if let image = image {
    widthHeightString += " width=\"\(image.size.width)\" height=\"\(image.size.height)\""
}

result += widthHeightString

Objective-C的:

NSURL *pathURL = [NSURL fileURLWithPath:attachmentFilePath];
NSString *path = [pathURL path];
NSData *data = [[NSFileManager defaultManager] contentsAtPath:path];

UIImage *image = [UIImage imageWithData:data];
NSString *base64String = [data base64EncodedStringWithOptions:0];
[result appendString:@"data:image/"];
[result appendString:attachmentType]; // jpg, gif etc.
[result appendString:@";base64,"];
[result appendString:base64String];

NSString *widthHeightString = @"\"";
if (image) {
    widthHeightString = [NSString stringWithFormat:@"\" width=\"%f\" height=\"%f\"", image.size.width, image.size.height];
}
[result appendString:widthHeightString];


Answer 9:

我使用的是下面。 有一些额外的东西我的工作,但你能看到我注释掉的和的loadRequest我代loadHTMLString电话。 希望这有助于直到他们修复bug。

import UIKit
import WebKit

class ViewController: UIViewController, WKScriptMessageHandler {

    var theWebView: WKWebView?

    override func viewDidLoad() {
        super.viewDidLoad()

        var path = NSBundle.mainBundle().pathForResource("index", ofType: "html", inDirectory:"www" )
        var url = NSURL(fileURLWithPath:path)
        var request = NSURLRequest(URL:url)
        var theConfiguration = WKWebViewConfiguration()

        theConfiguration.userContentController.addScriptMessageHandler(self, name: "interOp")

        theWebView = WKWebView(frame:self.view.frame, configuration: theConfiguration)

        let text2 = String.stringWithContentsOfFile(path, encoding: NSUTF8StringEncoding, error: nil)

        theWebView!.loadHTMLString(text2, baseURL: nil)

        //theWebView!.loadRequest(request)

        self.view.addSubview(theWebView)


    }

    func appWillEnterForeground() {

    }

    func appDidEnterBackground() {

    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    func userContentController(userContentController: WKUserContentController!, didReceiveScriptMessage message: WKScriptMessage!){
        println("got message: \(message.body)")

    }

}


Answer 10:

对于谁必须解决办法iOS8上在此问题:

如果您的网页并不复杂,你可能会选择使页面的单页中的应用。

换句话说,所有的资源嵌入到HTML文件。

要做到:1复制你的JS / CSS文件的内容转换成分别在HTML文件/标签; 2.将您的图像文件为SVG更换相应。 3.负载的页面之前,使用[webView的loadHTMLString:基本URL:],例如

这是一个有点不同,以一个造型SVG图像,但它不应该阻止你这么多。

看来,在网页渲染性能下降了一点,但它是值得拥有iOS8上/ 9/10下工作这样一个简单的解决方法。



Answer 11:

在同一行GCDWebServer的,我使用SImpleHttpServer( http://www.andyjamesdavies.com/blog/javascript/simple-http-server-on-mac-os-x-in-seconds ),然后用的loadRequest本地主机网址。 通过这种方法,你不必添加任何库,但该网站的文件将不会在捆绑所以这不会是交付。 正因为如此,这将是更适合于调试情况。



Answer 12:

我已经成功地使用在OS X复制PHP的Web服务器来临时/ www目录,我没有工作。 Python的SimpleHTTPServer抱怨想要阅读MIME类型,可能是沙盒问题。

下面是一个使用服务器php -S

let portNumber = 8080

let task = NSTask()
task.launchPath = "/usr/bin/php"
task.arguments = ["-S", "localhost:\(portNumber)", "-t", directoryURL.path!]
// Hide the output from the PHP server
task.standardOutput = NSPipe()
task.standardError = NSPipe()

task.launch()


Answer 13:

@ nacho4d解决方案是不错的。 我想改变它一点点,但我不知道如何去改变它在您的文章。 所以,我把它放在这里,我希望你不要介意。 谢谢。

如果你有一个WWW文件夹还有很多其他的文件,如PNG,CSS,JS等等,那么你必须所有文件复制到TMP / WWW文件夹。 例如,你有这样的WWW文件夹:

然后在夫特2.0:

override func viewDidLoad() {
    super.viewDidLoad()

    let path = NSBundle.mainBundle().resourcePath! + "/www";
    var fileURL = NSURL(fileURLWithPath: path)
    if #available(iOS 9.0, *) {
        let path = NSBundle.mainBundle().pathForResource("index", ofType: "html", inDirectory: "www")
        let url = NSURL(fileURLWithPath: path!)
        self.webView!.loadRequest(NSURLRequest(URL: url))
    } else {
        do {
            fileURL = try fileURLForBuggyWKWebView8(fileURL)
            let url = NSURL(fileURLWithPath: fileURL.path! + "/index.html")
            self.webView!.loadRequest( NSURLRequest(URL: url))
        } catch let error as NSError {
            print("Error: \(error.debugDescription)")
        }
    }
}

功能fileURLForBuggyWKWebView8从@ nacho4d复制:

func fileURLForBuggyWKWebView8(fileURL: NSURL) throws -> NSURL {
    // Some safety checks
    var error:NSError? = nil;
    if (!fileURL.fileURL || !fileURL.checkResourceIsReachableAndReturnError(&error)) {
        throw error ?? NSError(
            domain: "BuggyWKWebViewDomain",
            code: 1001,
            userInfo: [NSLocalizedDescriptionKey: NSLocalizedString("URL must be a file URL.", comment:"")])
    }

    // Create "/temp/www" directory
    let fm = NSFileManager.defaultManager()
    let tmpDirURL = NSURL.fileURLWithPath(NSTemporaryDirectory())
    try! fm.createDirectoryAtURL(tmpDirURL, withIntermediateDirectories: true, attributes: nil)

    // Now copy given file to the temp directory
    let dstURL = tmpDirURL.URLByAppendingPathComponent(fileURL.lastPathComponent!)
    let _ = try? fm.removeItemAtURL(dstURL)
    try! fm.copyItemAtURL(fileURL, toURL: dstURL)

    // Files in "/temp/www" load flawlesly :)
    return dstURL
}


Answer 14:

尝试使用

[webView loadHTMLString:htmlFileContent baseURL:baseURL];

看来它仍然工作。 然而。



文章来源: WKWebView not loading local files under iOS 8