WKWebView iOS 8에서 로컬 파일을 로드하지 않음
이전 iOS 8 베타의 경우 로컬 웹 앱(번들에 있음)을 로드하면 두 가지 모두에 잘 작동합니다.UIWebView
그리고.WKWebView
그리고 나는 심지어 새로운 것을 사용하여 웹 게임을 포팅했습니다.WKWebView
API.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 컨트롤러 소개에서 몇 초의 가치가 있는 수정이었습니다.
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:]을(를) 사용하는 방법의 예입니다.
웹 폴더를 프로젝트로 이동할 때 "폴더 참조 작성"을 선택합니다.
그런 다음 다음과 같은 코드를 사용합니다(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 프로젝트로 이동된 디렉터리의 예입니다.
임시 해결 방법: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
'programing' 카테고리의 다른 글
RAW(16) 열에 UUID를 삽입하는 방법 (0) | 2023.08.05 |
---|---|
내 SQL 표준 시간대 변경? (0) | 2023.08.05 |
개체 배열의 각도 업데이트 개체 (0) | 2023.08.05 |
첫 번째 콜이 자동 증분인 mysql에 데이터 INFILE을 로드하는 방법은 무엇입니까? (0) | 2023.08.05 |
적합한 메인 클래스를 찾을 수 없습니다. 'mainClass' 속성인 Springboot을 추가하십시오. (0) | 2023.08.05 |