Newer
Older
Productization_H5_IOS / template / Module / SYWebVC.swift
@zhangfeng zhangfeng on 8 Aug 2023 8 KB commit first
//
//  SYWebVC.swift
//
//  Created by 张丰 on 2023/6/8.
//

import UIKit
import WebKit
import Reachability
class SYWebVC: UIViewController {
    var urlStr = ""
    lazy var webview: WKWebView = WKWebView()
    lazy var progressbar: UIProgressView = UIProgressView()
    var native = XFNativeModule.init()
    
    var loadCount = 0
    /// 网络监听类
    lazy var reachability = try? Reachability()
    /// false没网 true有网
    var netWortStatus = true
    
    func regisJsHandler(isInstall:Bool) {
        let handerContro = self.webview.configuration.userContentController
        for fun in AppJsFunType.allCases {
            if isInstall {
                handerContro.add(self, name: fun.rawValue)
            } else {
                handerContro.removeScriptMessageHandler(forName: fun.rawValue)
            }
        }
    }
    
    deinit {
        self.webview.removeObserver(self, forKeyPath: "estimatedProgress")
        self.webview.scrollView.removeObserver(self, forKeyPath: "contentOffset")
    }
    init(_ url:String) {
        super.init(nibName: nil, bundle: nil)
        self.urlStr = url
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        self.webview.navigationDelegate = self
        self.view.addSubview(self.webview)
        
        self.webview.frame = self.view.frame
        self.webview.translatesAutoresizingMaskIntoConstraints = false
        self.view.addConstraints([
            self.webview.topAnchor.constraint(equalTo: self.view.topAnchor),
            self.webview.bottomAnchor.constraint(equalTo: self.view.bottomAnchor),
            self.webview.leadingAnchor.constraint(equalTo: self.view.leadingAnchor),
            self.webview.trailingAnchor.constraint(equalTo: self.view.trailingAnchor),
        ])
        
        self.webview.addSubview(self.progressbar)
        self.progressbar.tintColor = color_main
        self.setProgressBarPosition()
        
        webview.scrollView.addObserver(self, forKeyPath: "contentOffset", options: .new, context: nil)
        
        self.progressbar.progress = 0.1
        webview.addObserver(self, forKeyPath: "estimatedProgress", options: .new, context: nil)
        
        self.regisJsHandler(isInstall: true)
        NetworkStatusListener()
        self.loadWeb()
        
    }
    
    
    func setProgressBarPosition() {
        self.progressbar.translatesAutoresizingMaskIntoConstraints = false
        self.webview.removeConstraints(self.webview.constraints)
        self.webview.addConstraints([
            self.progressbar.topAnchor.constraint(equalTo: self.webview.topAnchor, constant: self.webview.scrollView.contentOffset.y * -1),
            self.progressbar.leadingAnchor.constraint(equalTo: self.webview.leadingAnchor),
            self.progressbar.trailingAnchor.constraint(equalTo: self.webview.trailingAnchor),
        ])
    }
    
    @objc
    func loadWeb() {
        
        if webview.url != nil {

            webview.reload()

        } else {
            guard let url = URL.init(string: self.urlStr) else { return }
            self.webview.load(URLRequest.init(url: url))
        }
        
//        guard let url = Bundle.main.url(forResource: "webte.html", withExtension: nil) else { return }
//        let req = URLRequest(url: url)
//        self.webview.load(req)
    }
    // MARK: - Web view progress
    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
        switch keyPath {
        case "estimatedProgress":
            if self.webview.estimatedProgress >= 1.0 {
                UIView.animate(withDuration: 0.3, animations: { () in
                    self.progressbar.alpha = 0.0
                }, completion: { finished in
                    self.progressbar.setProgress(0.0, animated: false)
                })
            } else {
                self.progressbar.isHidden = false
                self.progressbar.alpha = 1.0
                progressbar.setProgress(Float(self.webview.estimatedProgress), animated: true)
            }
            
        case "contentOffset":
            self.setProgressBarPosition()
            
        default:
            super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)
        }
    }
    
    
}
extension SYWebVC:WKNavigationDelegate,WKUIDelegate {
    func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
        
    }
    func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) {
        
    }
}

extension SYWebVC:WKScriptMessageHandler {
    func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
        SYLog("js调用原生的方法:\(message.name)")
        SYLog("js调用原生的方法的参数:\(message.body)")
        guard let type = AppJsFunType.init(rawValue: message.name) else { return }
        guard let param = message.body as? [String:Any] else { return }
        guard let data = param["data"] as? [String:Any] else { return }
        guard let callId = param["callId"] as? String else { return }
        
        switch type {
        case .initRCWithAppKey:
            guard let appkey = data["appKey"] as? String else { return }
            native.initRC(withAppKey: appkey, option: data)
            
        case .connectRC:
            guard let token = data["token"] as? String else { return }
            native.connectRC(token) { [weak self] value, keepAlive in
                guard let this = self else { return }
                this.callJS(callId: callId, data: value,keepAlive: keepAlive)
            }
            
        case .addRCConnectionListen:
            native.addRCConnectionListen { [weak self] value, keepAlive in
                guard let this = self else { return }
                this.callJS(callId: callId, data: value,keepAlive: keepAlive)
            }
        case .disConnectRC:
            native.disConnectRC()
            
        case .getLocation:
            native.getLocation(data) { [weak self] value, keepAlive in
                guard let this = self else { return }
                this.callJS(callId: callId, data: value,keepAlive: keepAlive)
            }
        case .stopLocation:
            native.stopLocation(data)
            
        case .isBackground:
            let isBackground = native.isBackground()
            self.callJS(callId: callId, data: ["isBackground":isBackground],keepAlive: false)
            
        case .callAction:
            native.callAction(data)
            
        case .getIt:
            debugPrint("回调成功")
        }
    }
}
extension SYWebVC {
    /// 调用JS
    func callJS(callId:String,data:Any?,keepAlive:Bool = false) {
        var param = [String:Any?]()
        param["keepAlive"] = keepAlive
        param["data"] = data
        let jsString = callId + "(" + convertDictionaryToString(dict: param) + ")"
        
        self.webview.evaluateJavaScript(jsString) { value, error in
            if let error {
                debugPrint(error)
            }else if let value {
                debugPrint(value)
            }
        }
    }
    
}


extension SYWebVC {
    /***** 网络状态监听部分(开始) *****/
    func NetworkStatusListener() {
        // 1、设置网络状态消息监听 2、获得网络Reachability对象
        NotificationCenter.default.addObserver(self, selector: #selector(self.reachabilityChanged),name: Notification.Name.reachabilityChanged,object: nil)
        do{
            // 3、开启网络状态消息监听
            try reachability?.startNotifier()
        }catch{
            print("could not start reachability notifier")
        }
        
    }
    // 主动检测网络状态
    @objc func reachabilityChanged(note: NSNotification) {
        
        switch reachability?.connection {
        case .wifi,.cellular:
            debugPrint("有网")
            netWortStatus = true
            if self.loadCount == 0 {
                self.loadWeb()
                self.loadCount  = 1
            } else {
//                self.emptyView.isHidden = true
            }
        default:
            netWortStatus = false
            debugPrint("断网")
        }
    }
    
}