Files
yingmeng-ios-switf/yinmeng-ios/Base/Web/WebViewController.swift
2024-03-28 19:56:25 +08:00

314 lines
10 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// WebViewController.swift
// yinmeng-ios
//
// Created by yinmeng on 2024/2/26.
//
import UIKit
import WebKit
import MJExtension
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 = {
let scriptMessage = WebViewWeakScriptMessage(target: self);
let _userContentController = WKUserContentController()
_userContentController.add(self, name: "getUid")
_userContentController.add(self, name: "getDeviceId")
_userContentController.add(self, name: "getTicket")
_userContentController.add(self, name: "getDeviceInfo")
_userContentController.add(self, name: "initShowNav")
_userContentController.add(self, name: "closeWebView")
_userContentController.add(self, name: "cancelAccount")
return _userContentController
}()
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 = "\(AppKeys.H5_URL)/\(url)"
}
self.url = url
}
self.navigationDelegate = navigationDelegate
}
override func viewDidLoad() {
super.viewDidLoad()
loadSubViews()
loadWebView()
}
deinit{
print("1111")
}
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() {
//KVOWKWebViewestimatedProgress
webview.addObserver(self, forKeyPath: "estimatedProgress", context: nil)
//KVOtitle
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
let cookie = "uid=\(AuthManager.userUid)"
let cookieScript = WKUserScript.init(source: "document.cookie = '\(cookie)';", injectionTime: .atDocumentStart, forMainFrameOnly: false)
self.userContentController.addUserScript(cookieScript)
let scale = "$('meta[name=description]').remove(); $('head').append( '<meta name=\"viewport\" content=\"width=device-width, initial-scale=1,user-scalable=no\">' );"
let scaleScript = WKUserScript.init(source: scale, injectionTime: .atDocumentEnd, forMainFrameOnly: false)
self.userContentController.addUserScript(scaleScript)
configuration.userContentController = self.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
webview.evaluateJavaScript("navigator.userAgent") {[weak self] res, error in
guard let self = self else{return}
if let text = res as? NSString{
if !text.contains("tutuAppIos erbanAppIos"){
let newText = (text as String) + "tutuAppIos erbanAppIos"
let dic = ["UserAgent":newText]
UserDefaults.standard.register(defaults: dic)
UserDefaults.standard.synchronize()
self.webview.customUserAgent = newText
}
}
}
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
webview.evaluateJavaScript("document.location.href") {[weak self] res, error in
guard let self = self else{return}
if let curUrl = res{
if message.name == "getUid"{
let uid = "getMessage(\"uid\",\(AuthManager.userUid))"
self.webview.evaluateJavaScript(uid) { other, error in
}
}else if message.name == "getTicket"{
let ticket = "getMessage(\"ticket\",\"\(AuthManager.ticket)\")"
self.webview.evaluateJavaScript(ticket) { other, error in
}
}else if message.name == "getDeviceId"{
let deviceId = "getMessage(\"deviceId\",\"\(APPUtils.currentDeveiceId)\")"
self.webview.evaluateJavaScript(deviceId) { other, error in
}
}else if message.name == "getDeviceInfo"{
let info = NSDictionary(dictionary: YMNetworkHelper.share.baseParameters)
if let infoText = info.mj_JSONString() {
let text = "getMessage(\"deviceInfo\",\(infoText))"
self.webview.evaluateJavaScript(text) { other, error in
}
}
}else if message.name == "initShowNav"{
if let body = message.body as? Int,body == 0{
if self.navigationController != nil{
self.navigationController?.setNavigationBarHidden(true, animated: false)
}
}
}else if message.name == "closeWebView"{
if let body = message.body as? Int,body == 0{
if self.navigationController != nil{
self.navigationController?.popViewController(animated: true)
}
}
}else if message.name == "cancelAccount"{
AuthViewModel.authVM.logout()
}
}
}
}
}
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)
}
}