228 lines
6.5 KiB
Swift
228 lines
6.5 KiB
Swift
//
|
||
// WebViewController.swift
|
||
// yinmeng-ios
|
||
//
|
||
// Created by yinmeng on 2024/2/26.
|
||
//
|
||
|
||
import UIKit
|
||
import WebKit
|
||
class WebViewWeakScriptMessage: NSObject, WKScriptMessageHandler {
|
||
|
||
private(set) weak var target: WKScriptMessageHandler?
|
||
|
||
required init(target: WKScriptMessageHandler?) {
|
||
self.target = target
|
||
}
|
||
|
||
|
||
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
|
||
target?.userContentController(userContentController, didReceive: message)
|
||
}
|
||
|
||
}
|
||
|
||
class WebViewController: BaseViewController {
|
||
|
||
typealias OnReceiveMessage = (_ msg: WKScriptMessage) -> Void
|
||
|
||
private(set) lazy var webview = makeWebView()
|
||
|
||
private(set) var progressView = UIProgressView()
|
||
|
||
private lazy var userContentController = WKUserContentController()
|
||
|
||
private var callbacks: [String: [OnReceiveMessage]] = [:]
|
||
|
||
private(set) weak var navigationDelegate: WKNavigationDelegate?
|
||
|
||
private(set) var url: String?
|
||
var isHalf:Bool = false
|
||
convenience init(
|
||
url: String?,
|
||
navigationDelegate: WKNavigationDelegate? = nil,isHalf:Bool = false
|
||
) {
|
||
self.init(nibName: nil, bundle: nil)
|
||
self.url = url
|
||
self.isHalf = isHalf
|
||
if var url = url {
|
||
if !url.hasPrefix("http") {
|
||
url = "\(H5_URL)/\(url)"
|
||
}
|
||
self.url = url
|
||
}
|
||
self.navigationDelegate = navigationDelegate
|
||
}
|
||
|
||
override func viewDidLoad() {
|
||
super.viewDidLoad()
|
||
loadSubViews()
|
||
loadWebView()
|
||
}
|
||
|
||
override func viewWillAppear(_ animated: Bool) {
|
||
super.viewWillAppear(animated)
|
||
addObserve()
|
||
}
|
||
|
||
override func viewWillDisappear(_ animated: Bool) {
|
||
super.viewWillDisappear(animated)
|
||
removeObserve()
|
||
}
|
||
|
||
override func viewDidLayoutSubviews() {
|
||
super.viewDidLayoutSubviews()
|
||
|
||
view.bringSubviewToFront(progressView)
|
||
}
|
||
|
||
private func loadSubViews() {
|
||
|
||
if self.isHalf{
|
||
let bakcBtn = UIButton()
|
||
bakcBtn.addTarget(self, action: #selector(dissViewAction), for: .touchUpInside)
|
||
view.addSubview(bakcBtn)
|
||
bakcBtn.snp.makeConstraints { make in
|
||
make.edges.equalTo(view)
|
||
}
|
||
view.addSubview(webview)
|
||
view.addSubview(progressView)
|
||
progressView.snp.makeConstraints { make in
|
||
make.top.equalTo(view).offset(0)
|
||
make.left.right.equalTo(view).offset(0)
|
||
make.height.equalTo(1)
|
||
}
|
||
view.backgroundColor = .clear
|
||
webview.snp.makeConstraints { make in
|
||
|
||
make.left.bottom.right.equalTo(view)
|
||
make.height.equalTo(ScreenHeight * 0.65)
|
||
}
|
||
}else{
|
||
view.addSubview(webview)
|
||
view.addSubview(progressView)
|
||
progressView.snp.makeConstraints { make in
|
||
make.top.equalTo(view).offset(0)
|
||
make.left.right.equalTo(view).offset(0)
|
||
make.height.equalTo(1)
|
||
}
|
||
webview.snp.makeConstraints { make in
|
||
make.top.equalTo(view).offset(1)
|
||
make.left.right.bottom.equalTo(view)
|
||
}
|
||
}
|
||
|
||
|
||
progressView.trackTintColor = .clear
|
||
progressView.transform = .init(scaleX: 1, y: 1.5)
|
||
progressView.alpha = 0
|
||
}
|
||
|
||
@objc func dissViewAction(){
|
||
self.dismiss(animated: true)
|
||
}
|
||
|
||
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
|
||
if let object = object as? WKWebView, object == webview {
|
||
if keyPath == "estimatedProgress" {
|
||
progressView.setProgress(Float(webview.estimatedProgress), animated: true)
|
||
return
|
||
}
|
||
}
|
||
|
||
if keyPath == "title" {
|
||
title = webview.title
|
||
return
|
||
}
|
||
}
|
||
|
||
func addObserve() {
|
||
//添加KVO,WKWebView有一个属性estimatedProgress,就是当前网页加载的进度,所以监听这个属性
|
||
webview.addObserver(self, forKeyPath: "estimatedProgress", context: nil)
|
||
//添加KVO,监听title属性
|
||
webview.addObserver(self, forKeyPath: "title", context: nil)
|
||
}
|
||
|
||
func removeObserve() {
|
||
webview.removeObserver(self, forKeyPath: "estimatedProgress")
|
||
webview.removeObserver(self, forKeyPath: "title")
|
||
}
|
||
|
||
func loadWebView() {
|
||
guard let url = url,
|
||
let theUrl = URL(string: url),
|
||
let _ = theUrl.scheme,
|
||
let _ = theUrl.host else {
|
||
return
|
||
}
|
||
|
||
webview.load(URLRequest(url: theUrl))
|
||
}
|
||
|
||
func reloadWebViewWithUrl(_ url: String) {
|
||
self.url = url
|
||
loadWebView()
|
||
}
|
||
|
||
func makeWebView() -> WKWebView {
|
||
let configuration = WKWebViewConfiguration()
|
||
configuration.mediaTypesRequiringUserActionForPlayback = .all
|
||
configuration.allowsInlineMediaPlayback = true
|
||
configuration.allowsPictureInPictureMediaPlayback = true
|
||
configuration.selectionGranularity = .character
|
||
configuration.userContentController = userContentController
|
||
|
||
let preferences = WKPreferences()
|
||
if #available(iOS 14, *) {
|
||
let webpagePreferences = WKWebpagePreferences()
|
||
webpagePreferences.allowsContentJavaScript = true
|
||
configuration.defaultWebpagePreferences = webpagePreferences
|
||
} else {
|
||
preferences.javaScriptEnabled = true
|
||
}
|
||
preferences.javaScriptCanOpenWindowsAutomatically = true
|
||
preferences.minimumFontSize = 10
|
||
configuration.preferences = preferences
|
||
let webview = WKWebView(frame: UIScreen.main.bounds, configuration: configuration)
|
||
webview.navigationDelegate = self
|
||
return webview
|
||
}
|
||
|
||
func dicValueString(_ dic:[String:Any]) ->String? {
|
||
let data = try? JSONSerialization.data(withJSONObject: dic,options: [])
|
||
let str = String(data: data!,encoding:String.Encoding.utf8)
|
||
return str
|
||
}
|
||
|
||
}
|
||
|
||
extension WebViewController: WKScriptMessageHandler {
|
||
|
||
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
|
||
//TODO: 拦截一些h5的事件
|
||
}
|
||
}
|
||
|
||
extension WebViewController: WKNavigationDelegate {
|
||
|
||
func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
|
||
progressView.alpha = 1
|
||
navigationDelegate?.webView?(webview, didStartProvisionalNavigation: navigation)
|
||
}
|
||
|
||
|
||
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
|
||
UIView.animate(withDuration: 0.2) {
|
||
self.progressView.alpha = 0
|
||
}
|
||
navigationDelegate?.webView?(webview, didFinish: navigation)
|
||
}
|
||
|
||
func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) {
|
||
UIView.animate(withDuration: 0.2) {
|
||
self.progressView.alpha = 0
|
||
}
|
||
navigationDelegate?.webView?(webView, didFailProvisionalNavigation: navigation, withError: error)
|
||
}
|
||
}
|