iOS分享世界iOS Developer

MG--Swift3.0加载网页

2017-04-08  本文已影响253人  Mg明明就是你
//  WKWebViewController.swift
//  ProductionReport

import UIKit
import WebKit

class WKWebViewController: UIViewController {
    // MARK: - lazy
    fileprivate lazy var webView: WKWebView = { [unowned self] in
        // 创建webveiew
        // 创建一个webiview的配置项
        let configuretion = WKWebViewConfiguration()

        // Webview的偏好设置
        configuretion.preferences = WKPreferences()
        configuretion.preferences.minimumFontSize = 10
        configuretion.preferences.javaScriptEnabled = true
        // 默认是不能通过JS自动打开窗口的,必须通过用户交互才能打开
        configuretion.preferences.javaScriptCanOpenWindowsAutomatically = false

        // 通过js与webview内容交互配置
        configuretion.userContentController = WKUserContentController()

        // 添加一个JS到HTML中,这样就可以直接在JS中调用我们添加的JS方法
        let js = "function showAlert() { alert('在载入webview时通过Swift注入的JS方法'); }"
        let script = WKUserScript(source: js, injectionTime: .atDocumentStart,// 在载入时就添加JS
            forMainFrameOnly: true) // 只添加到mainFrame中
        configuretion.userContentController.addUserScript(script)

        // 添加一个名称,就可以在JS通过这个名称发送消息:
        // window.webkit.messageHandlers.AppModel.postMessage({body: 'xxx'})
        configuretion.userContentController.add(self as WKScriptMessageHandler, name: "MingModel")

        let webView = WKWebView(frame: self.view.bounds, configuration: configuretion)
        webView.navigationDelegate = self
        webView.uiDelegate = self
        return webView
    }()
    fileprivate lazy var progressView: UIProgressView = {
        let progressView = UIProgressView(progressViewStyle: .bar)
        progressView.frame.size.width = self.view.frame.size.width
        // 这里可以改进度条颜色
        progressView.tintColor = UIColor.green
        return progressView
    }()
    
    // MARK: - 生命周期
    override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
        super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
        view.addSubview(webView)
        view.insertSubview(progressView, aboveSubview: webView)
    }
    convenience init(navigationTitle: String, urlStr: String) {
        self.init(nibName: nil, bundle: nil)
        navigationItem.title = navigationTitle
        webView.load(URLRequest(url: URL(string: urlStr)!))
    }
    convenience init(navigationTitle: String, url: URL) {
        self.init(nibName: nil, bundle: nil)
        navigationItem.title = navigationTitle
        webView.load(URLRequest(url:  url))
    }
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        self.edgesForExtendedLayout = UIRectEdge()

        webView.addObserver(self, forKeyPath: "loading", options: .new, context: nil)
        webView.addObserver(self, forKeyPath: "title", options: .new, context: nil)
        webView.addObserver(self, forKeyPath: "estimatedProgress", options: .new, context: nil)
    }

    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
        if keyPath == "loading" {
//            print("loading")
        } else if keyPath == "title" {
            title = self.webView.title
        } else if keyPath == "estimatedProgress" {
            print(webView.estimatedProgress)
            progressView.setProgress(Float(webView.estimatedProgress), animated: true)
        }
        
        UIView.animate(withDuration: 0.5) { 
            self.progressView.isHidden = (self.progressView.progress == 1)
        }

        if webView.isLoading {
            // 手动调用JS代码
            let js = "callJsAlert()"
            webView.evaluateJavaScript(js, completionHandler: { (any, err) in
                debugPrint(any)
            })
        }
    }
    
    // 移除观察者
    deinit {
        webView.removeObserver(self, forKeyPath: "loading")
        webView.removeObserver(self, forKeyPath: "title")
        webView.removeObserver(self, forKeyPath: "estimatedProgress")
    }
}

// MARK: - WKScriptMessageHandler
extension WKWebViewController: WKScriptMessageHandler {
    // WKScriptMessageHandler:必须实现的函数,是APP与js交互,提供从网页中收消息的回调方法
    func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
        print(message.body)
        print(message.webView)
    }
}

// MARK: - WKNavigationDelegate
extension WKWebViewController: WKNavigationDelegate {
    // 决定导航的动作,通常用于处理跨域的链接能否导航。WebKit对跨域进行了安全检查限制,不允许跨域,因此我们要对不能跨域的链接
    // 单独处理。但是,对于Safari是允许跨域的,不用这么处理。
    func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
        let hostname = (navigationAction.request as NSURLRequest).url?.host?.lowercased()
        
        print(hostname)
        print(navigationAction.navigationType)
        // 处理跨域问题
        if navigationAction.navigationType == .linkActivated && hostname!.contains(".baidu.com") {
            // 手动跳转
            UIApplication.shared.openURL(navigationAction.request.url!)
            
            // 不允许导航
            decisionHandler(.cancel)
        } else {
            decisionHandler(.allow)
        }
    }
    
    func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
        print(#function)
    }
    
    func webView(_ webView: WKWebView, decidePolicyFor navigationResponse: WKNavigationResponse, decisionHandler: @escaping (WKNavigationResponsePolicy) -> Void) {
        print(#function)
        decisionHandler(.allow)
    }
    
    func webView(_ webView: WKWebView, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
        print(#function)
        completionHandler(.performDefaultHandling, nil)
    }

}

// MARK: - WKUIDelegate
extension WKWebViewController: WKUIDelegate {
    func webView(_ webView: WKWebView, runJavaScriptAlertPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping () -> Void) {
        let alert = UIAlertController(title: "tip", message: message, preferredStyle: .alert)
        alert.addAction(UIAlertAction(title: "ok", style: .default, handler: { (_) -> Void in
            // We must call back js
            completionHandler()
        }))
        
        self.present(alert, animated: true, completion: nil)
    }
    
    func webView(_ webView: WKWebView, runJavaScriptConfirmPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping (Bool) -> Void) {
        completionHandler(true)
    }
    
    func webView(_ webView: WKWebView, runJavaScriptTextInputPanelWithPrompt prompt: String, defaultText: String?, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping (String?) -> Void) {
        completionHandler("woqu")
    }
    
    func webViewDidClose(_ webView: WKWebView) {
        print("close")
    }
}
WKWebView
//  WebViewController.swift
//  ProductionReport

import UIKit

// MARK: - Class: WebViewController
class WebViewController: UIViewController {
    // MARK: - 属性
    fileprivate var webView = UIWebView(frame: .zero)
    fileprivate var urlStr: String?
    fileprivate let loadProgressAnimationView: LoadProgressAnimationView = LoadProgressAnimationView(frame: CGRect(x: 0, y: 0, width: MGScreenW, height: 3))
    
    // MARK: - 生命周期
    override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
        super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
        view.addSubview(webView)
        webView.addSubview(loadProgressAnimationView)
        webView.scalesPageToFit = true
    }
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    convenience init(navigationTitle: String, urlStr: String) {
        self.init(nibName: nil, bundle: nil)
        navigationItem.title = navigationTitle
        webView.loadRequest(URLRequest(url: URL(string: urlStr)!))
        self.urlStr = urlStr
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        view.frame = MGScreenBounds
        automaticallyAdjustsScrollViewInsets = true
        view.backgroundColor = UIColor.white
        view.backgroundColor = UIColor.colorWithCustom(r: 230, g: 230, b: 230)
        buildRightItemBarButton()
        
        webView.frame = CGRect(x: 0, y: navHeight, width: MGScreenW, height: view.mg_height)
        webView.backgroundColor = UIColor.colorWithCustom(r: 230, g: 230, b: 230)
        webView.delegate = self
        webView.dataDetectorTypes = .all // 设置某些数据变为链接形式,这个枚举可以设置如电话号,地址,邮箱等转化为链接
        webView.mediaPlaybackAllowsAirPlay = true //设置音频播放是否支持ari play功能
        webView.suppressesIncrementalRendering = true // 设置是否将数据加载如内存后渲染界面
        webView.keyboardDisplayRequiresUserAction = true // 设置用户交互模式
//        webView.paginationMode = .topToBottom // 这个属性用来设置一种模式,当网页的大小超出view时,将网页以翻页的效果展示
        webView.scrollView.contentInset = UIEdgeInsets(top: -navHeight, left: 0, bottom: navHeight, right: 0)
    }
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
    }
    
    
    // MARK: - 导航栏
    private func buildRightItemBarButton() {
        let rightButton = UIButton(frame: CGRect(x: 0, y: 0, width: 60, height: 44))
        rightButton.setImage(UIImage(named: "v2_refresh"), for: UIControlState.normal)
        rightButton.contentEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: -53)
        rightButton.addTarget(self, action: #selector(WebViewController.refreshClick), for: UIControlEvents.touchUpInside)
        navigationItem.rightBarButtonItem = UIBarButtonItem(customView: rightButton)
    }
    
    // MARK: - Action
    func refreshClick() {
        if urlStr != nil && urlStr!.characters.count > 1 {
            webView.loadRequest(URLRequest(url: URL(string: urlStr!)!))
        }
    }
}

// MARK: - UIWebViewDelegate
extension WebViewController: UIWebViewDelegate {
    func webViewDidStartLoad(_ webView: UIWebView) {
        loadProgressAnimationView.startLoadProgressAnimation()
    }
    
    func webViewDidFinishLoad(_ webView: UIWebView) {
        loadProgressAnimationView.endLoadProgressAnimation()
    }
    
    func webView(_ webView: UIWebView, didFailLoadWithError error: Error) {
        showHint(hint: "\(error)")
        loadProgressAnimationView.endLoadProgressAnimation()
    }
    
//    func webView(_ webView: UIWebView, shouldStartLoadWith request: URLRequest, navigationType: UIWebViewNavigationType) -> Bool {
//        let str = request.url?.absoluteString
//        if (str?.hasPrefix("tel"))! {
//            UIApplication.shared.openURL((URL(string: str!))!)
//        }
//        return true
//    }
}


// MARK: - 
// MARK: - Class: LoadProgressAnimationView
class LoadProgressAnimationView: UIView {
    
    var viewWidth: CGFloat = 0
    override var frame: CGRect {
        willSet {
            if frame.size.width == viewWidth {
                self.isHidden = true
            }
            super.frame = frame
        }
    }
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        
        viewWidth = frame.size.width
        backgroundColor = UIColor.randomColor()
        self.frame.size.width = 0
    }
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    
    // MARK: - 加载进度动画
    func startLoadProgressAnimation() {
        self.frame.size.width = 0
        isHidden = false
        UIView.animate(withDuration: 0.8, animations: { () -> Void in
            self.frame.size.width = self.viewWidth * 0.70
            
        }) { (finish) -> Void in
            DispatchQueue.main.asyncAfter(deadline: .now() + 0.08, execute: {
                UIView.animate(withDuration: 0.3, animations: { 
                    self.frame.size.width = self.viewWidth * 0.85
                })
            })
        }
    }
    
    func endLoadProgressAnimation() {
        UIView.animate(withDuration: 0.1, animations: { () -> Void in
            self.frame.size.width = self.viewWidth*0.99
        }) { (finish) -> Void in
            self.isHidden = true
        }
    }
}
UIWebView.png
  • 轻轻点击,关注我简书

轻轻点击,关注我简书

轻轻点击,关注我微博

浏览我的GitHub


  • 扫一扫,关注我

扫一扫,关注我.jpg
上一篇下一篇

猜你喜欢

热点阅读