iOS-swiftJS 和 iOS的相遇

Swift与JS的交互

2015-11-18  本文已影响3104人  海青

Swift与JS的交互

原理

同Object-C与JS交互的大同小异,只是方法形式改变了。
首先我们需要引入iOS7.0出来的JavaScriptCore.framework

JavaScriptCore

实战

Swift 与 JS 基本数据类型转换

在Swift中我们推荐使用let类声明类(引用类型),这是Swift加强了安全机制的结果。
首先初始化JS执行环境let context = JSContext(),并且为了捕获JS执行过程中得异常,我们给self.jsContext?.exceptionHandler闭包赋值。然后我们就正式开始与JS的交互,调用context.evaluateScript()方法执行任何JS代码,返回结果都是JSValue类型,使用toObject()方法转化成Swift对象,当然对象转换是一一对应的(如JS int类型应该转换成Swift Int类型)。我们还可以使用objectForKeyedSubscript()调用下角标函数(OC中我们直接使用[@"属性或者对象"])来取得JSContext执行环境的对象或者方法,也可以取得JSValue一系列的属性等。

代码如下

    //声明执行环境
    let context = JSContext();
    self.jsContext = context;
    //捕获异常
    self.jsContext?.exceptionHandler = {(jsContext:JSContext!,exception:JSValue!) ->Void in
        jsContext.exception = exception;
        print(exception);
    };
    let value = context.evaluateScript("2 + 2");
    print(value.toObject());
    //或者 区别print更简洁
    NSLog("\(value.toObject())");
    //直接定义JS数组
    context.evaluateScript("var array = ['徐海青',123]")
    //下标获取JS数组
    let arrayValue = context.objectForKeyedSubscript("array")
    if(!arrayValue.isArray){
        print("arrayValue不是数组")
        return
    }
    //两种方式获取属性
    print("arrayValue 长度\(arrayValue.objectForKeyedSubscript("length")),第一种方式获取的值\(arrayValue.valueAtIndex(0)),第二种方式获取的值\(arrayValue.objectAtIndexedSubscript(1)),第二种方式获取的长度\(arrayValue.valueForProperty("length"))");
    //两种方式设置array,越界自动扩展
    arrayValue.setObject("赵杰文", atIndexedSubscript: 4);
    arrayValue.setValue("水草草", atIndex: 6);
    //打印最后的array
    print(arrayValue);
    arrayValue.toArray()
    let array = arrayValue.toArray();
    //打印转换后的数组
    print(array);

函数调用

我们使用JS注入方法到执行环境,然后使用objectForKeyedSubscript()取出方法

    self.jsContext = JSContext();
    //JS异常处理
    self.jsContext?.exceptionHandler = { (jsContext:JSContext!,exception:JSValue!) ->Void in
        jsContext.exception = exception;
        print(exception);
    }
    /*  js 函数
        var func = function(value){
        if(value < 0) return;
        if(value === 0) return 1;
        return value * function(value - 1);
        }
    */
    //拼接JS
    let funStr = "var fun = function (value){" +
                 "if(value < 0) return;" +
                 "if(value === 0) return 1;" +
                 "return value * fun(value - 1);" +
                 "}";
    //打印插入前的函数
    print(funStr);
    //插入JS
    self.jsContext?.evaluateScript(funStr);
    //下标获取函数
    //let jsFunc = self.jsContext?.objectForKeyedSubscript("fun");
    //或者
    let jsFunc = self.jsContext?.evaluateScript("fun");
    //打印插入后函数,应该和前面一样
    print(jsFunc);
    //传入参数
   let result = jsFunc?.callWithArguments([5]);
    //打印结果
    print("result = \(result)");

使用闭包

申明Swift闭包block,通过 self.jsContext?.setObject() 赋值

    self.jsContext = JSContext();
    //JS异常处理
    self.jsContext?.exceptionHandler = { (jsContext:JSContext!,exception:JSValue!) ->Void in
        jsContext.exception = exception;
        print(exception);
    }
    //往JS注入类
    let block = {(name:String,qq:String) -> JSValue in
        //let context = JSContext.currentContext();
        let object = JSValue(newObjectInContext: self.jsContext);
        object.setObject(name, forKeyedSubscript: "name");
        object.setValue(qq, forProperty: "qq");
        return object;
    }
    print(block);
    self.jsContext?.setObject(block("xuhaiqing","1716329344"), forKeyedSubscript: "User");
    //验证是否注入成功
    let user = self.jsContext?.evaluateScript("User");
    print("user.name = \(user?.objectForKeyedSubscript("name")) and user.qq =  \(user?.valueForProperty("qq"))" )

使用JSExport 方便构造,我们强烈推荐使用这种方式与JS交互

    var user = User(name: "xuhaiqing", qq: "1716329344");
    user.jsContext = self.jsContext;
    user.webView = self.webView;
    //关联
    print(self.jsContext);
    self.jsContext?.setObject(user, forKeyedSubscript: "SwiftModel");
    print(user);
    //修改关联后的值
    self.jsContext?.evaluateScript("SwiftModel.name = 'zhaojiewen'");
    self.jsContext?.evaluateScript("SwiftModel.descriptions()");
    print(user.name);
    print(user.qq);

User 类

    //
    //  User.swift
    //  SwiftJSDemo
    //
    //  Created by haodf on 15/11/12.
    //  Copyright © 2015年 haodf. All rights reserved.
    //

    import Foundation
    import UIKit
    import JavaScriptCore
    @objc protocol UserJsToSwiftDelegate : JSExport{
    var name:(String){get set};
    var qq:(String){get set};
    func callSystemCamera();
    func showAlert(title:String,msg:String);
    func callWithDict(dic:[String:AnyObject]);
    func descriptions();
    }
    @objc class User :NSObject,UserJsToSwiftDelegate,UIImagePickerControllerDelegate,UINavigationControllerDelegate {
var name:(String);
var qq:(String);
var webView:UIWebView?
var jsContext:JSContext?
//author 徐海青
//
//初始化
init(name:(String),qq:(String)){
    self.name = name;
    self.qq = qq;
}
//author 徐海青
//
//调用系统照相机
@objc func callSystemCamera(){
    let imagePickerViewController = UIImagePickerController();
    imagePickerViewController.delegate = self;
    UIApplication.sharedApplication().keyWindow?.addSubview(imagePickerViewController.view);
    UIApplication.sharedApplication().keyWindow?.rootViewController?.addChildViewController(imagePickerViewController);
}
//author 徐海青
//
//弹框显示提示信息
@objc func showAlert(title:String, msg: String) {
    //调用系统的alert
// let alertViewController = UIAlertController();
// UIApplication.sharedApplication().keyWindow?.addSubview(alertViewController.view);
//        UIApplication.sharedApplication().keyWindow?.rootViewController?.addChildViewController(alertViewController);
    //调用JS的alert
    let jsValue = self.jsContext?.objectForKeyedSubscript("alertFunc");
    jsValue?.callWithArguments([title,msg]);
    
}
//author 徐海青
//
//双向交互
@objc func callWithDict(dic: [String : AnyObject]) {
    print(self.jsContext);
    let funStr = "var swiftInsertIntoJsFunc = function(arg){" +
    "document.getElementById('swiftInsertIntoJsSpan').innerHTML = arg['name'];" +
    "}";
    //打印插入前的函数
    print(funStr);
    //插入JS
    self.jsContext?.evaluateScript(funStr);
    //下标获取函数
    //let jsFunc = self.jsContext?.objectForKeyedSubscript("fun");
    //或者
    let jsFunc = self.jsContext?.evaluateScript("swiftInsertIntoJsFunc");
    //let insertFunc = self.jsContext?.objectForKeyedSubscript("swiftInsertIntoJsFunc");
    print(dic);
    print(jsFunc);
    jsFunc?.callWithArguments([dic]);
}

//author 徐海青
//
//打印时显示的信息
    @objc func descriptions() {
        print("user.name = \(self.name) and user.qq = \(self.qq)")
    }

    @objc func imagePickerControllerDidCancel(picker: UIImagePickerController) {
     picker.view.removeFromSuperview();
        picker.removeFromParentViewController();
    }

}
上一篇下一篇

猜你喜欢

热点阅读