MG--Swift3.0加載網(wǎng)頁(yè)

  • 一戳表、WKWebView

//  WKWebViewController.swift
//  ProductionReport

import UIKit
import WebKit

class WKWebViewController: UIViewController {
    // MARK: - lazy
    fileprivate lazy var webView: WKWebView = { [unowned self] in
        // 創(chuàng)建webveiew
        // 創(chuàng)建一個(gè)webiview的配置項(xiàng)
        let configuretion = WKWebViewConfiguration()

        // Webview的偏好設(shè)置
        configuretion.preferences = WKPreferences()
        configuretion.preferences.minimumFontSize = 10
        configuretion.preferences.javaScriptEnabled = true
        // 默認(rèn)是不能通過(guò)JS自動(dòng)打開窗口的徽级,必須通過(guò)用戶交互才能打開
        configuretion.preferences.javaScriptCanOpenWindowsAutomatically = false

        // 通過(guò)js與webview內(nèi)容交互配置
        configuretion.userContentController = WKUserContentController()

        // 添加一個(gè)JS到HTML中程腹,這樣就可以直接在JS中調(diào)用我們添加的JS方法
        let js = "function showAlert() { alert('在載入webview時(shí)通過(guò)Swift注入的JS方法'); }"
        let script = WKUserScript(source: js, injectionTime: .atDocumentStart,// 在載入時(shí)就添加JS
            forMainFrameOnly: true) // 只添加到mainFrame中
        configuretion.userContentController.addUserScript(script)

        // 添加一個(gè)名稱跺涤,就可以在JS通過(guò)這個(gè)名稱發(fā)送消息:
        // 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
        // 這里可以改進(jìn)度條顏色
        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 {
            // 手動(dòng)調(diào)用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:必須實(shí)現(xiàn)的函數(shù)草慧,是APP與js交互,提供從網(wǎng)頁(yè)中收消息的回調(diào)方法
    func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
        print(message.body)
        print(message.webView)
    }
}

// MARK: - WKNavigationDelegate
extension WKWebViewController: WKNavigationDelegate {
    // 決定導(dǎo)航的動(dòng)作吸祟,通常用于處理跨域的鏈接能否導(dǎo)航瑟慈。WebKit對(duì)跨域進(jìn)行了安全檢查限制,不允許跨域屋匕,因此我們要對(duì)不能跨域的鏈接
    // 單獨(dú)處理葛碧。但是,對(duì)于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)
        // 處理跨域問(wèn)題
        if navigationAction.navigationType == .linkActivated && hostname!.contains(".baidu.com") {
            // 手動(dòng)跳轉(zhuǎn)
            UIApplication.shared.openURL(navigationAction.request.url!)
            
            // 不允許導(dǎo)航
            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 // 設(shè)置某些數(shù)據(jù)變?yōu)殒溄有问较怂洌@個(gè)枚舉可以設(shè)置如電話號(hào)缘琅,地址,郵箱等轉(zhuǎn)化為鏈接
        webView.mediaPlaybackAllowsAirPlay = true //設(shè)置音頻播放是否支持ari play功能
        webView.suppressesIncrementalRendering = true // 設(shè)置是否將數(shù)據(jù)加載如內(nèi)存后渲染界面
        webView.keyboardDisplayRequiresUserAction = true // 設(shè)置用戶交互模式
//        webView.paginationMode = .topToBottom // 這個(gè)屬性用來(lái)設(shè)置一種模式廓推,當(dāng)網(wǎng)頁(yè)的大小超出view時(shí),將網(wǎng)頁(yè)以翻頁(yè)的效果展示
        webView.scrollView.contentInset = UIEdgeInsets(top: -navHeight, left: 0, bottom: navHeight, right: 0)
    }
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
    }
    
    
    // MARK: - 導(dǎo)航欄
    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: - 加載進(jìn)度動(dòng)畫
    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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末翩隧,一起剝皮案震驚了整個(gè)濱河市樊展,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌堆生,老刑警劉巖专缠,帶你破解...
    沈念sama閱讀 210,914評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異淑仆,居然都是意外死亡涝婉,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,935評(píng)論 2 383
  • 文/潘曉璐 我一進(jìn)店門蔗怠,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)墩弯,“玉大人,你說(shuō)我怎么就攤上這事寞射∮婀ぃ” “怎么了?”我有些...
    開封第一講書人閱讀 156,531評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵桥温,是天一觀的道長(zhǎng)引矩。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么旺韭? 我笑而不...
    開封第一講書人閱讀 56,309評(píng)論 1 282
  • 正文 為了忘掉前任氛谜,我火速辦了婚禮,結(jié)果婚禮上区端,老公的妹妹穿的比我還像新娘值漫。我一直安慰自己,他們只是感情好珊燎,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,381評(píng)論 5 384
  • 文/花漫 我一把揭開白布惭嚣。 她就那樣靜靜地躺著,像睡著了一般悔政。 火紅的嫁衣襯著肌膚如雪晚吞。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,730評(píng)論 1 289
  • 那天谋国,我揣著相機(jī)與錄音槽地,去河邊找鬼。 笑死芦瘾,一個(gè)胖子當(dāng)著我的面吹牛捌蚊,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播近弟,決...
    沈念sama閱讀 38,882評(píng)論 3 404
  • 文/蒼蘭香墨 我猛地睜開眼缅糟,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了祷愉?” 一聲冷哼從身側(cè)響起窗宦,我...
    開封第一講書人閱讀 37,643評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體棺聊,經(jīng)...
    沈念sama閱讀 44,095評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡谆膳,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,448評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,566評(píng)論 1 339
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖寄纵,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情脖苏,我是刑警寧澤擂啥,帶...
    沈念sama閱讀 34,253評(píng)論 4 328
  • 正文 年R本政府宣布,位于F島的核電站帆阳,受9級(jí)特大地震影響哺壶,放射性物質(zhì)發(fā)生泄漏屋吨。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,829評(píng)論 3 312
  • 文/蒙蒙 一山宾、第九天 我趴在偏房一處隱蔽的房頂上張望至扰。 院中可真熱鬧,春花似錦资锰、人聲如沸敢课。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,715評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)直秆。三九已至,卻和暖如春鞭盟,著一層夾襖步出監(jiān)牢的瞬間圾结,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,945評(píng)論 1 264
  • 我被黑心中介騙來(lái)泰國(guó)打工齿诉, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留筝野,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,248評(píng)論 2 360
  • 正文 我出身青樓粤剧,卻偏偏與公主長(zhǎng)得像歇竟,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子抵恋,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,440評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容