programing

WKWebView iOS 8에서 로컬 파일을 로드하지 않음

lastmoon 2023. 8. 5. 10:54
반응형

WKWebView iOS 8에서 로컬 파일을 로드하지 않음

이전 iOS 8 베타의 경우 로컬 웹 앱(번들에 있음)을 로드하면 두 가지 모두에 잘 작동합니다.UIWebView그리고.WKWebView그리고 나는 심지어 새로운 것을 사용하여 웹 게임을 포팅했습니다.WKWebViewAPI.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여전히 작동), 로드되거나 실행되는 것이 없는 것 같습니다.로그에 오류가 있습니다.

대샌한확생수없다습니에 대한 할 수 ./

올바른 방향으로 안내하는 데 도움이 필요합니까?감사합니다!

그들은 마침내 버그를 해결했습니다!이제 사용할 수 있습니다.-[WKWebView loadFileURL:allowingReadAccessToURL:]WWDC 2015 비디오 504 Safari View 컨트롤러 소개에서 몇 초의 가치가 있는 수정이었습니다.

https://developer.apple.com/videos/wwdc/2015/?id=504

iOS8 ~ iOS10용(스위프트 3)

Dan Fabulish의 답변에 따르면 이것은 곧 해결되지 않을 으로 보이는 WKWebView의 버그이며 해결책이 있다고 말했습니다:)

저는 단지 여기서 해결책을 보여주고 싶어서 대답하는 것입니다.https://github.com/shazron/WKWebViewFIleUrlTest 표시된 IMO 코드는 대부분의 사람들이 관심이 없는 관련 없는 세부 사항으로 가득 차 있습니다.

해결 방법은 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)
        }
    }
}

는 WKWebView의 URL을 수 없습니다.loadRequest:방법.http://www.openradar.me/18039024

다음을 통해 컨텐츠를 로드할 수 있습니다.loadHTMLString: 만약 당신의 이라면 작동하지 않습니다.URL이 파일: URL이지만 여전히 작동하지 않습니다.

이 원하는할 수 인 iOS 9가 . [WKWebView loadFileURL:allowingReadAccessToURL:].

iOS 8에 대한 해결 방법이 있는데, https://github.com/shazron/WKWebViewFIleUrlTest 의 Objective-Cheer에서 shazron에 의해 입증되어 파일을 복사하고 거기서 로드할 수 있습니다.

스위프트에서 일하고 있다면, 대신 나코스4d의 샘플을 사용해볼 수 있습니다.(또한 Shazron의 샘플보다 훨씬 짧기 때문에 Shazron의 코드에 문제가 있다면 대신 사용해 보십시오.)

iOS 9에서 [WKWebView loadFileURL:allowingReadAccessToURL:]을(를) 사용하는 방법의 예입니다.

웹 폴더를 프로젝트로 이동할 때 "폴더 참조 작성"을 선택합니다.

enter image description here

그런 다음 다음과 같은 코드를 사용합니다(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 프로젝트로 이동된 디렉터리의 예입니다.

enter image description here

임시 해결 방법:GuidoMB에서 제안한 GCD WebServer를 사용하고 있습니다.

먼저 번들 "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:.

[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:FILE_PATH]
    allowingReadAccessToURL: [NSURL fileURLWithPath:FILE_PATH]
];

Dan Fabulich가 언급한 솔루션 외에도 XWebView는 또 다른 해결 방법입니다.[WKWebView loadFileURL:allowingReadAccessToURL:]은(는) 확장을 통해 구현됩니다.

저는 아직 코멘트를 할 수 없어서 별도의 답변으로 글을 올립니다.

이것은 nacho4d의 솔루션의 목표-c 버전입니다.지금까지 본 것 중 최고의 해결 방법입니다.

- (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;
}

같이 더 큰에 로컬 :<img src="file://...">아직 장치에 나타나지 않아서 NSData에 이미지 파일을 로드하고 src 문자열을 데이터 자체로 교체하여 표시할 수 있었습니다.WKWebView에 로드할 HTML 문자열을 빌드하는 데 도움이 되는 샘플 코드입니다. 여기서 결과는 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

목표-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];

저는 아래를 사용하고 있습니다.내가 추가로 작업하고 있는 것이 있지만, 당신은 내가 loadRequest를 코멘트 아웃하고 load를 대체하고 있는 곳을 볼 수 있습니다.HTML 문자열 호출.그들이 버그를 고칠 때까지 이것이 도움이 되기를 바랍니다.

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)")

    }

}

iOS8에서 이 문제를 해결해야 하는 사용자:

페이지가 복잡하지 않은 경우 페이지를 단일 페이지 응용프로그램으로 만들 수 있습니다.

즉, 모든 리소스를 html 파일에 포함하는 것입니다.

작업: 1. js/css 파일의 내용을 html 파일의 /tags로 각각 복사하고, 2. 이미지 파일을 svg로 변환하여 이를 대체합니다. 3. [webView load]를 사용하여 이전과 같이 페이지를 로드합니다.HTMLString: baseURL:], 예

svg 이미지를 스타일링하는 것과는 조금 달랐지만, 당신을 너무 막아서는 안 됩니다.

페이지 렌더링 성능이 다소 떨어지는 것 같았지만 iOS 8/9/10에서 이러한 간단한 해결 방법을 사용할 가치가 있었습니다.

GCD WebServer의 동일한 라인에서 SimpleHttpServer(http://www.andyjamesdavies.com/blog/javascript/simple-http-server-on-mac-os-x-in-seconds) 를 사용하고 있으며 localhost URL과 함께 Request를 로드합니다.이 방법을 사용하면 라이브러리를 추가할 필요가 없지만 웹 사이트 파일이 번들에 포함되지 않으므로 전송할 수 없습니다.따라서 디버그 사례에 적합합니다.

OS X에서 PHP의 웹 서버를 사용할 수 있었습니다. 임시/www 디렉토리에 복사하는 것은 제게 효과가 없었습니다.파이썬 심플HTTPS 서버는 샌드박스 문제인 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()

@나초4d 용액이 좋습니다.저는 그것을 조금 바꾸고 싶은데 당신의 게시물에서 어떻게 바꿔야 할지 모르겠습니다.그래서 여기에 두었습니다. 괜찮으시길 바랍니다.감사해요.

만약 당신이 ww 폴더를 가지고 있다면 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)")
        }
    }
}

함수 파일버그에 대한 URLWKWebView8은 @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
}

사용해 보십시오.

[webView loadHTMLString:htmlFileContent baseURL:baseURL];

아직 작동 중인 것 같습니다.아직.

언급URL : https://stackoverflow.com/questions/24882834/wkwebview-not-loading-local-files-under-ios-8

반응형