MG--Swift3.0加载网页

作者: Mg明明就是你 | 来源:发表于2017-04-08 13:59 被阅读253次
    • 一、WKWebView

    //  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
    • 二、UIWebView

    //  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

    相关文章

      网友评论

      本文标题:MG--Swift3.0加载网页

      本文链接:https://www.haomeiwen.com/subject/zqdhwttx.html