要点
native -> js
主要是通过 直接 执行一段 js 函数代码
1,context.evaluateScript("SwiftFunc()")//异步
2, webView.stringByEvaluatingJavaScriptFromString("SwiftFunc()")//同步
//同步
js -> native
1.通过context?.setObject(unsafeBitCast(temp, to: AnyObject.self), forKeyedSubscript: "test2" as (NSCopying & NSObjectProtocol)!)
2,通过新建model后 通过 setObject注入model, 而model要实现protocol,protocol是要 执行的方法。 在js中onclick 中 实现 model.func()
swift文件
// Swift 调用JS 方法 (无参数)
@IBAction func swift_js_pargram(_ sender: AnyObject) {
_ = self.context?.evaluateScript("Swift_JS1()")
// self.webView.stringByEvaluatingJavaScriptFromString("Swift_JS1()") // 此方法也可行
}
// Swift 调用JS 方法 (有参数)
@IBAction func swift_js_nopargam(_ sender: AnyObject) {
_ = self.context?.evaluateScript("Swift_JS2('oc' ,'Swift')")
// self.webView.stringByEvaluatingJavaScriptFromString("Swift_JS2('oc','swift')") // 此方法也可行
}
func menthod1() {
print("JS调用了无参数swift方法")
}
func menthod2(_ str1: String, str2: String) {
print("JS调用了有参数swift方法:参数为\(str1),\(str2)")
}
func webView(_ webView: UIWebView, didFailLoadWithError error: Error) {
print(error)
}
}
extension ViewController: UIWebViewDelegate {
func webView(_ webView: UIWebView, shouldStartLoadWith request: URLRequest, navigationType: UIWebViewNavigationType) -> Bool {
return true
}
func webViewDidStartLoad(_ webView: UIWebView) {
print("webViewDidStartLoad----")
}
func webViewDidFinishLoad(_ webView: UIWebView) {
print("webViewDidFinishLoad----")
self.context = webView.value(forKeyPath: "documentView.webView.mainFrame.javaScriptContext") as? JSContext
// JS调用了无参数swift方法
let temp1: @convention(block) () ->() = {
self.menthod1()
}
self.context?.setObject(unsafeBitCast(temp1, to: AnyObject.self), forKeyedSubscript: "showAlart1" as (NSCopying & NSObjectProtocol)!)
// JS调用了有参数swift方法
let temp2: @convention(block) () ->() = {
let array = JSContext.currentArguments() // 这里接到的array中的内容是JSValue类型
for object in array! {
print(object)
}
self.menthod2((array?[0] as AnyObject).toString(), str2: (array?[1] as AnyObject).toString())
}
self.context?.setObject(unsafeBitCast(temp2, to: AnyObject.self), forKeyedSubscript: "test2" as (NSCopying & NSObjectProtocol)!)
// 模型注入的方法
let model = JSObjCModel()
model.controller = self
model.jsContext = context
// 这一步是将OCModel这个模型注入到JS中,在JS就可以通过OCModel调用我们暴露的方法了。
context?.setObject(model, forKeyedSubscript: "OCModel" as (NSCopying & NSObjectProtocol)!)
}
}
@objc protocol JavaScriptSwiftDelegate: JSExport {
func callSystemCamera()
func showAlert(_ title: String, msg: String)
func callWithDict(_ dict: [String: AnyObject])
func jsCallObjcAndObjcCallJsWithDict(_ dict: [String: AnyObject])
}
@objc class JSObjCModel: NSObject, JavaScriptSwiftDelegate ,UIImagePickerControllerDelegate,UIActionSheetDelegate,UINavigationControllerDelegate {
weak var controller: UIViewController?
weak var jsContext: JSContext?
func callSystemCamera() {
print(controller.debugDescription)
let imagePickerController:UIImagePickerController = UIImagePickerController()
imagePickerController.delegate = self
imagePickerController.allowsEditing = true//true为拍照、选择完进入图片编辑模式
imagePickerController.sourceType = .camera
controller?.present(imagePickerController, animated: true, completion: nil)
// let jsFunc = self.jsContext?.objectForKeyedSubscript("jsFunc");
// _ = jsFunc?.call(withArguments: []);
}
func showAlert(_ title: String, msg: String) {
DispatchQueue.main.async { () -> Void in
let alert = UIAlertController(title: title, message: msg, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "ok", style: .default, handler: nil))
self.controller?.present(alert, animated: true, completion: nil)
}
}
// JS调用了我们的方法
func callWithDict(_ dict: [String : AnyObject]) {
print("js call objc method: callWithDict, args: %@", dict)
}
// JS调用了我们的又去
func jsCallObjcAndObjcCallJsWithDict(_ dict: [String : AnyObject]) {
print("js call objc method: jsCallObjcAndObjcCallJsWithDict, args: %@", dict)
// let jsParamFunc = self.jsContext?.objectForKeyedSubscript("jsParamFunc");
// let dict = NSDictionary(dictionary: ["age": 18, "height": 168, "name": "lili"])
//
// _ = jsParamFunc?.call(withArguments: [dict])
//
// _ = JSContext.currentArguments()
let url = Bundle.main.url(forResource: "rc_ac_audio_file_icon.png", withExtension: nil)
let data = NSData.init(contentsOf: url!)
let jsPar = jsContext?.objectForKeyedSubscript("showImgFunc");
// let argument = image as? NSData ?? NSData()
_ = jsPar?.call(withArguments: [data!])
}
//
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
// let image = info[UIImagePickerControllerEditedImage] //as? UIImage ?? UIImage()
//
// let jsPar = jsContext?.objectForKeyedSubscript("jsParamFunc");
// let argument = image as? NSData ?? NSData()
//
// _ = jsPar?.call(withArguments: [argument])
//
}
html文件
<button type="button" onclick="JS_Swift1()">JS调用Swift方法(无参)</button> </br>
<button type="button" onclick="JS_Swift2()">JS调用Swift方法(传参)</button>
<!-- 模型注入 -->
<b>model 注入</b>
<div style="margin-top: 100px">
<input type="button" value="Call ObjC system camera" onclick="OCModel.callSystemCamera()">
<input type="button" value="Call ObjC system alert" onclick="OCModel.showAlertMsg('js title', 'js message')">
</div>
</hr>
<div>
<input type="button" value="Call ObjC func with JSON " onclick="OCModel.callWithDict({'name': 'testname', 'age': 10, 'height': 170})">
<input type="button" value="Call ObjC func with JSON and ObjC call js func to pass args." onclick="OCModel.jsCallObjcAndObjcCallJsWithDict({'name': 'testname', 'age': 10, 'height': 170})">
</div>
<div bgcolor="#ddd0">
<span id="jsParamFuncSpan" style="color: red; font-size: 50px;">interHtml</span>
</div>
<div bgcolor="#0000">
<img id="imgShowDiv" src="" width="300px" height="300px" style="display: block;" />
</div>
<script type="text/javascript">
function jsFunc() {
alert('Objective-C call js to show alert');
}
// 注意哦,如果JS写错,可能在OC调用JS方法时,都会出错哦。
var jsParamFunc = function(argument) {
document.getElementById('jsParamFuncSpan').innerHTML
= argument['name'];
}
网友评论