WKWebView 基本使用

1.WKWebView - 读取本地HTML(ios9以前)

当使用loadRequest来读取本地的HTML时,WKWebView是无法读取成功的,后台会出现如下的提示:

Could not create a sandbox extension for

原因是WKWebView是不允许通过loadRequest的方法来加载本地根目录的HTML文件。
而在iOS9的SDK中加入了以下方法来加载本地的HTML文件:

if #available(iOS 9.0, *) {
    WKWebView.loadFileURL:allowingReadAccessToURL:
}

但是在iOS9以下的版本是没提供这个便利的方法的。以下为解决方案的思路,就是在iOS9以下版本时,先将本地HTML文件的数据copy到tmp目录中,然后再使用loadRequest来加载。但是如果在HTML中加入了其他资源文件,例如js,css,image等必须一同copy到temp中。这个是最蛋疼的事情了。

解决方法如下
//将文件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的方法时

optional func webView(_ webView: WKWebView!, decidePolicyForNavigationAction navigationAction: WKNavigationAction!, decisionHandler decisionHandler: ((WKNavigationActionPolicy) -> Void)!)

需执行decisionHandler的block。

例如:

func webView(webView: WKWebView, decidePolicyForNavigationAction navigationAction: WKNavigationAction, decisionHandler: (WKNavigationActionPolicy) -> Void) {
        let url = navigationAction.request.URL
        if let url = url, host = url.host {
            if WebLink.isNeedHost(host) {
                decisionHandler(.Allow)
                return
            }

            UIApplication.sharedApplication().openURL(url)
            decisionHandler(.Cancel)
            return
        }
        decisionHandler(.Cancel)
    }

3.WKWebView - JS执行方法

WKWebView JS执行方法与UIWebView不一样了。

func evaluateJavaScript(_ javaScriptString: String!, completionHandler completionHandler: ((AnyObject!, NSError!) -> Void)!)

completionHandler 拥有两个参数,一个是返回错误,一个可以返回执行脚本后的返回值

4.WKWebView - Toolbar (KVO)

WKWebView 底部Toolbar,前进后退以及刷新的功能,采用KVO监听的方式


let webView: WKWebView = WKWebView()

var webLink: WebLink?

@IBOutlet var webLinkToolbar: WebLinkToolbar!

private var kvoContext = 0

// MARK: Initialize
override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
    super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
}

required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
}

convenience init(_ webLink: WebLink) {
    self.init(nibName: nil, bundle: nil)
    self.webLink = webLink
}

override func viewDidLoad() {
    super.viewDidLoad()

    /*! @abstract A Boolean value indicating whether horizontal swipe gestures
     will trigger back-forward list navigations.
     @discussion The default value is NO.
     */
    webView.allowsBackForwardNavigationGestures = true
    webView.navigationDelegate = self
    webView.translatesAutoresizingMaskIntoConstraints = false

    webView.addObserver(self, forKeyPath: "loading", options: .New, context: &kvoContext)

    //add constraints for webview
    self.view.backgroundColor = UIColor.whiteColor()
    self.view.insertSubview(webView, atIndex: 0)
    self.view.addConstraints([
            NSLayoutConstraint(item: self.view, attribute: .Top, relatedBy: .Equal, toItem: webView, attribute: .Top, multiplier: CGFloat(1.0), constant: CGFloat(0.0)),
            NSLayoutConstraint(item: self.view, attribute: .Right, relatedBy: .Equal, toItem: webView, attribute: .Right, multiplier: CGFloat(1.0), constant: CGFloat(0.0)),
            NSLayoutConstraint(item: self.view, attribute: .Bottom, relatedBy: .Equal, toItem: webView, attribute: .Bottom, multiplier: CGFloat(1.0), constant: CGFloat(0.0)),
            NSLayoutConstraint(item: self.view, attribute: .Left, relatedBy: .Equal, toItem: webView, attribute: .Left, multiplier: CGFloat(1.0), constant: CGFloat(0.0))
        ])
    self.view.updateConstraints()
    self.view.setNeedsLayout()
    self.view.layoutIfNeeded()

    //load toolbar form xib
    NSBundle.mainBundle().loadNibNamed("WebLinkToolbar", owner: self, options: nil)
    self.webLinkToolbar.translatesAutoresizingMaskIntoConstraints = false
    self.webLinkToolbar.goBackButton.addTarget(self, action: "goBack:", forControlEvents: .TouchUpInside)
    self.webLinkToolbar.goForwardButton.addTarget(self, action: "goForward:", forControlEvents: .TouchUpInside)
    self.webLinkToolbar.reloadButton.addTarget(self, action: "reload:", forControlEvents: .TouchUpInside)
    self.view.addSubview(self.webLinkToolbar)

    //add constraints for toolbar
    var constraints = [NSLayoutConstraint]()    
    constraints.appendContentsOf(NSLayoutConstraint.constraintsWithVisualFormat("H:|[webLinkToolbar]|", options: [], metrics: nil, views: ["webLinkToolbar": self.webLinkToolbar]))
    constraints.appendContentsOf(NSLayoutConstraint.constraintsWithVisualFormat("V:[webLinkToolbar(44)]|", options: [], metrics: nil, views: ["webLinkToolbar": self.webLinkToolbar]))
    NSLayoutConstraint.activateConstraints(constraints)

}
override func viewWillAppear(animated: Bool) {
      super.viewWillAppear(animated)

// Web ViewのInsetを変更
if self.webLinkToolbar.hidden {
    let inset = UIEdgeInsetsZero
    self.webView.scrollView.contentInset = inset
    self.webView.scrollView.scrollIndicatorInsets = inset
}
else {
    let inset = UIEdgeInsets(top: 0.0, left: 0.0, bottom: self.webLinkToolbar.frame.height, right: 0.0)
    self.webView.scrollView.contentInset = inset
    self.webView.scrollView.scrollIndicatorInsets = inset
}

// タイトルを設定
    self.navigationItem.title = webLink.title()

// ロード
    if #available(iOS 9.0, *) {
        switch webLink {
        case .License, .LocalAgreement:
            let url = NSURL.init(fileURLWithPath: webLink.urlString())
            webView.loadFileURL(url, allowingReadAccessToURL: url)
            return

        default:
            break;
        }
    }
    webView.loadRequest(webLink.request())
}
// MARK: KVO
override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) {
    if context == &kvoContext {
        if keyPath == "loading" {
            self.webLinkToolbar.goBackButton.enabled = self.webView.canGoBack
            self.webLinkToolbar.goForwardButton.enabled = self.webView.canGoForward
        }
    }
    else {
        super.observeValueForKeyPath(keyPath, ofObject: object, change: change, context: context)
    }
}

// MARK: Action for Web Link Toolbar
func goBack(sender: UIButton) {
    // back
    self.webView.goBack()
}

func goForward(sender: UIButton) {
    // forward
    self.webView.goForward()
}

func reload(sender: UIButton) {
    if let currentURL = self.webView.URL {
        let request = NSURLRequest(URL: currentURL)
        self.webView.loadRequest(request)
    }
}
/*
deinit must remove observer
*/
deinit {
    self.webView.removeObserver(self, forKeyPath: "loading", context: &kvoContext)
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值