update with message handler string

This commit is contained in:
Xinlei(Ryan) Pan 2020-04-01 17:16:23 -04:00
parent bfe706908f
commit 83e04f0a12
2 changed files with 32 additions and 42 deletions

View File

@ -27,25 +27,19 @@ import WebKit
override open func setupView() {
super.setupView()
let webView = createWebView(messageHandler: mvmWebViewMessageHandler, jsScript: nil)
let webView = createWebView(messageHandler: mvmWebViewMessageHandler)
addSubview(webView)
NSLayoutConstraint.constraintPinSubview(toSuperview: webView)
self.webView = webView
pinSpinnerView()
}
func createWebView(messageHandler: String?, jsScript:String?) -> WKWebView {
func createWebView(messageHandler: String?) -> WKWebView {
let wkUserController = WKUserContentController()
if let messageHandlerName = messageHandler {
wkUserController.add(self, name: messageHandlerName)
}
//server driven addition script
if let jsScript = jsScript {
let wkScript = WKUserScript(source: jsScript, injectionTime: .atDocumentStart, forMainFrameOnly: true)
wkUserController.addUserScript(wkScript)
}
let wkConfig = WKWebViewConfiguration()
wkConfig.userContentController = wkUserController
let webView = WKWebView(frame: .zero, configuration: wkConfig)
@ -59,33 +53,29 @@ import WebKit
// MARK: - MVMCoreUIMoleculeViewProtocol
override open func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) {
super.set(with: model, delegateObject, additionalData)
guard let model = model as? WebViewModel else { return }
self.delegateObject = delegateObject
if model.callHandler != nil || model.jsScript != nil {
/*
webView's configuration property is immutable.
In order to add call handler into webview, need to create a new webview.
*/
webView?.removeFromSuperview()
let webView = createWebView(messageHandler: model.callHandler, jsScript:model.jsScript)
addSubview(webView)
NSLayoutConstraint.constraintPinSubview(toSuperview: webView)
self.webView = webView
}
//init height for loading spinner
webViewHeight = webView?.heightAnchor.constraint(equalToConstant: 50)
webViewHeight = webView?.heightAnchor.constraint(equalToConstant: 44)
webViewHeight?.isActive = true
if let height = model.height {
if let height = webviewModel?.height {
webViewHeight?.constant = height
dynamicHeight = false
}
if let url = model.url {
if let url = webviewModel?.url {
webView?.load(URLRequest(url: url))
} else if let htmlString = model.htmlString {
} else if let htmlString = webviewModel?.htmlString {
webView?.loadHTMLString(htmlString, baseURL: nil)
}
if let borderColor = webviewModel?.borderColor?.cgColor {
webView?.layer.borderWidth = 1.0
webView?.layer.borderColor = borderColor
} else {
webView?.layer.borderWidth = 0.0
webView?.layer.borderColor = UIColor.clear.cgColor
}
bringSubviewToFront(loadingSpinner)
}
@ -95,8 +85,8 @@ import WebKit
loadingSpinner.clipsToBounds = true
loadingSpinner.translatesAutoresizingMaskIntoConstraints = false
loadingSpinner.heightAnchor.constraint(equalToConstant: 50.0).isActive = true
loadingSpinner.widthAnchor.constraint(equalToConstant: 50.0).isActive = true
loadingSpinner.heightAnchor.constraint(equalToConstant: 44.0).isActive = true
loadingSpinner.widthAnchor.constraint(equalToConstant: 44.0).isActive = true
loadingSpinner.centerXAnchor.constraint(equalTo: centerXAnchor).isActive = true
loadingSpinner.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true
loadingSpinner.resumeSpinner()
@ -114,7 +104,6 @@ extension WebView : WKUIDelegate {
if !dynamicHeight {
return
}
/* was using "document.readyState" to check the state, while evaluateJavaScript "document.readyState",only works when webview contains userscrpt.otherwise, it would return WKErrorDomain Code=4 "A JavaScript exception occurred".
so webView.isLoading to check load finished state
*/
@ -157,14 +146,20 @@ extension WebView : WKNavigationDelegate {
// MARK: - WKScriptMessageHandler
extension WebView: WKScriptMessageHandler {
public func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
if message.name == mvmWebViewMessageHandler, let actionMap = message.body as? [AnyHashable: Any] {
if message.name == mvmWebViewMessageHandler, let text = message.body as? String {
/*
receiving JavaScript func webkit.messageHandlers.{callHandler}.postMessage(body);
if body is dictionary
MVMCoreActionHanlder handleAction
if body is string, will decode to actionmodel.
use legacy MVMCoreActionHanlder handleAction method for now
*/
MVMCoreActionHandler.shared()?.handleAction(with: actionMap, additionalData: nil, delegateObject: self.delegateObject)
if let data = text.data(using: .utf8) {
do {
let actionMap = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any]
MVMCoreActionHandler.shared()?.handleAction(with: actionMap, additionalData: nil, delegateObject: self.delegateObject)
} catch {
//actionModel should report error when actionhandler is finshed with actionmodel
}
}
}
}
}

View File

@ -15,8 +15,7 @@ import Foundation
public var url: URL?
public var htmlString: String?
public var height: CGFloat?
public var jsScript: String?
public var callHandler: String?
public var borderColor: Color?
public var buttonMap: [String: ButtonModel]?
private enum CodingKeys: String, CodingKey{
@ -26,8 +25,7 @@ import Foundation
case htmlString
case height
case buttonMap
case jsScript
case callHandler
case borderColor
}
required public init(from decoder: Decoder) throws {
@ -37,8 +35,7 @@ import Foundation
htmlString = try typeContainer.decodeIfPresent(String.self, forKey: .htmlString)
height = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .height)
buttonMap = try typeContainer.decodeIfPresent([String: ButtonModel].self, forKey: .buttonMap)
jsScript = try typeContainer.decodeIfPresent(String.self, forKey: .jsScript)
callHandler = try typeContainer.decodeIfPresent(String.self, forKey: .callHandler)
borderColor = try typeContainer.decodeIfPresent(Color.self, forKey: .borderColor)
}
public func encode(to encoder: Encoder) throws {
@ -48,8 +45,6 @@ import Foundation
try container.encodeIfPresent(url, forKey: .url)
try container.encodeIfPresent(htmlString, forKey: .htmlString)
try container.encodeIfPresent(height, forKey: .height)
try container.encodeIfPresent(jsScript, forKey: .jsScript)
try container.encodeIfPresent(callHandler, forKey: .callHandler)
try container.encodeIfPresent(borderColor, forKey: .borderColor)
}
}