WKWebViewで遭遇したピットを使用
5642 ワード
1.ios 9以前のバージョンでローカルHTMLを読み込んだ問題
loadRequestを使用してローカルのHTMLを読み込むと、WKWebViewは正常に読み込めません.バックグラウンドでは、
解決策は以下の通り
1.Objective-C:
2.Swift
2.WKWebView-WKNavigationDelegate使用
特に、以下のdelegateの方法を使用する場合
decisionHandlerのblockを実行する必要があります.
例:
3.WKWebView-JS実行方法
WKWebView JSの実行方法はUIWebViewとは異なります.
completionHandlerには2つのパラメータがあります.1つはエラーを返し、1つはスクリプトを実行した後の戻り値を返すことができます.
loadRequestを使用してローカルのHTMLを読み込むと、WKWebViewは正常に読み込めません.バックグラウンドでは、
Could not create a sandbox extension for /
が表示されます.なぜなら、WKWebViewはローカルルートディレクトリのHTMLファイルをloadRequestでロードできないためです.iOS 9のSDKには、ローカルのHTMLファイルをロードする方法が追加されています.[WKWebView loadFileURL:allowingReadAccessToURL:]
ですが、iOS 9以下のバージョンではこの便利な方法は提供されていません.iOS 9の次のバージョンでは、ローカルHTMLファイルのデータcopyをtmpディレクトリにコピーしてからloadRequestを使用してロードするソリューションを以下に示します.ただし、HTMLにjs、css、imageなどの他のリソースファイルが追加されている場合は、一緒にtempにコピーする必要があります.これは一番痛いことです.解決策は以下の通り
1.Objective-C:
// copy tmp
- (NSURL *)fileURLForBuggyWKWebView8:(NSURL *)fileURL {
NSError *error = nil;
if (!fileURL.fileURL || ![fileURL checkResourceIsReachableAndReturnError:&error]) {
return nil;
}
// Create "/temp/www" directory
NSFileManager *fileManager= [NSFileManager defaultManager];
NSURL *temDirURL = [[NSURL fileURLWithPath:NSTemporaryDirectory()] URLByAppendingPathComponent:@"www"];
[fileManager createDirectoryAtURL:temDirURL withIntermediateDirectories:YES attributes:nil error:&error];
NSURL *dstURL = [temDirURL URLByAppendingPathComponent:fileURL.lastPathComponent];
// Now copy given file to the temp directory
[fileManager removeItemAtURL:dstURL error:&error];
[fileManager copyItemAtURL:fileURL toURL:dstURL error:&error];
// Files in "/temp/www" load flawlesly :)
return dstURL;
}
//
NSString *path = [[NSBundle mainBundle] pathForResource:@"indexoff" ofType:@"html"];
if(path){
if ([[UIDevice currentDevice].systemVersion floatValue] >= 9.0) {
// iOS9. One year later things are OK.
NSURL *fileURL = [NSURL fileURLWithPath:path];
[self.webView loadFileURL:fileURL allowingReadAccessToURL:fileURL];
} else {
// iOS8. Things can be workaround-ed
// Brave people can do just this
// fileURL = try! pathForBuggyWKWebView8(fileURL)
// webView.loadRequest(NSURLRequest(URL: fileURL))
NSURL *fileURL = [self.fileHelper fileURLForBuggyWKWebView8:[NSURL fileURLWithPath:path]];
NSURLRequest *request = [NSURLRequest requestWithURL:fileURL];
[self.webView loadRequest:request];
}
}
2.Swift
// copy tmp
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()).URLByAppendingPathComponent("www")
try! fm.createDirectoryAtURL(tmpDirURL, withIntermediateDirectories: true, attributes: nil)
// Now copy given file to the temp directory
let dstURL = tmpDirURL.URLByAppendingPathComponent(fileURL.lastPathComponent!)
let _ = try? fileMgr.removeItemAtURL(dstURL)
try! fm.copyItemAtURL(fileURL, toURL: dstURL)
// Files in "/temp/www" load flawlesly :)
return dstURL
}
//
var filePath = NSBundle.mainBundle().pathForResource("file", ofType: "pdf")
if #available(iOS 9.0, *) {
// iOS9. One year later things are OK.
webView.loadFileURL(fileURL, allowingReadAccessToURL: fileURL)
} else {
// iOS8. Things can be workaround-ed
// Brave people can do just this
// fileURL = try! pathForBuggyWKWebView8(fileURL)
// webView.loadRequest(NSURLRequest(URL: fileURL))
do {
fileURL = try fileURLForBuggyWKWebView8(fileURL)
webView.loadRequest(NSURLRequest(URL: fileURL))
} catch let error as NSError {
print("Error: " + error.debugDescription)
}
}
2.WKWebView-WKNavigationDelegate使用
特に、以下のdelegateの方法を使用する場合
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
decisionHandlerのblockを実行する必要があります.
例:
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
NSURLRequest *request = navigationAction.request;
WMPageActionType actionType = ActionTypeNone;
WKNavigationActionPolicy actionPolicy = WKNavigationActionPolicyAllow;
if([request.URL.absoluteString hasPrefix:OC_CLOSE_REQUEST]){
actionType = ActionTypeClose;
actionPolicy = WKNavigationActionPolicyCancel;
}
if(self.actionDelegate && [self.actionDelegate respondsToSelector:@selector(webView:action:type:)]) {
[self.actionDelegate webView:webView action:navigationAction type:actionType];
}
// ,
decisionHandler(actionPolicy);
}
3.WKWebView-JS実行方法
WKWebView JSの実行方法はUIWebViewとは異なります.
- (void)evaluateJavaScript:(NSString *)javaScriptString completionHandler:(void (^)(id, NSError *))completionHandler;
completionHandlerには2つのパラメータがあります.1つはエラーを返し、1つはスクリプトを実行した後の戻り値を返すことができます.