利用JavaScriptCore自定义计算器

2020-10-05  本文已影响0人  LonnieQ

在JavaScriptCore中,我们可以给JSContext实例通过下标函数注册函数和变量。然后我们可以利用js代码调用注册的函数和变量来进行计算。代码如下:

#import <UIKit/UIKit.h>

@interface ViewController : UIViewController
@end

#import "ViewController.h"
@import JavaScriptCore;
@interface ViewController ()
@property (nonatomic, retain) UILabel * label;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.label = [UILabel new];
    [self.view addSubview:self.label];
    self.label.numberOfLines = 0;
    self.label.font = [UIFont preferredFontForTextStyle: UIFontTextStyleBody];
    self.label.translatesAutoresizingMaskIntoConstraints = false;
    [self.view addConstraints: @[
        [self.label.leadingAnchor constraintEqualToAnchor: self.view.leadingAnchor constant:16],
        [self.label.trailingAnchor constraintEqualToAnchor: self.view.trailingAnchor constant:16],
        [self.label.topAnchor constraintEqualToAnchor: self.view.topAnchor constant:16],
        [self.label.bottomAnchor constraintEqualToAnchor: self.view.bottomAnchor constant:16],
    ]];
    
    JSContext * context = [[JSContext alloc] init];
    
    context[@"sin"] = ^(double a) {
        return sin(a);
    };
    context[@"cos"] = ^(double a) {
        return cos(a);
    };
    context[@"tan"] = ^(double a) {
        return tan(a);
    };
    context[@"asin"] = ^(double a) {
        return asin(a);
    };
    context[@"acos"] = ^(double a) {
        return acos(a);
    };
    context[@"atan"] = ^(double a) {
        return atan(a);
    };
    context[@"sinh"] = ^(double a) {
        return sinh(a);
    };
    context[@"cosh"] = ^(double a) {
        return cosh(a);
    };
    context[@"tanh"] = ^(double a) {
        return tanh(a);
    };
    context[@"asinh"] = ^(double a) {
        return asinh(a);
    };
    context[@"acosh"] = ^(double a) {
        return acosh(a);
    };
    context[@"atanh"] = ^(double a) {
        return atanh(a);
    };
    context[@"pow"] = ^(double a, double b) {
        return pow(a, b);
    };
    context[@"sqrt"] = ^(double a) {
        return sqrt(a);
    };
    context[@"hypot"] = ^(double a, double b){
        return hypot(a, b);
    };
    context[@"pi"] = [JSValue valueWithDouble:M_PI inContext: context];
    context[@"e"] = [JSValue valueWithDouble:M_E inContext: context];
    NSArray<NSString*> * expressions = @[@"e", @"pi", @"sin(pi/3)", @"cos(pi/3)", @"tan(pi/3)", @"asin(1)", @"acos(1)", @"atan(1)", @"sinh(pi/3)", @"cosh(pi/3)", @"tanh(pi/3)", @"asinh(0.5)", @"acosh(1.1)", @"atanh(0.5)", @"pow(100, 2)", @"sqrt(33)", @"hypot(3, 4)"];
    NSMutableString * string = [NSMutableString new];
    [expressions enumerateObjectsUsingBlock:^(NSString * _Nonnull script, NSUInteger idx, BOOL * _Nonnull stop) {
        [string appendFormat:@"%@=%@\n", script, [context evaluateScript: script]];
    }];
    self.label.text = string;
}

显示结果如下:


截屏2020-10-05 23.37.15.png

以上仅仅适用于Objective-C, 如果是Swift语言, 我们需要先定义一个继承自JSExport协议的协议,在这个协议定义接口暴露给JavaScriptCore, 这些接口的输入参数和输出参数需要是Swift基本数据类型。注册的对象需要实现这样的协议。以下是一个简单的例子:

import JavaScriptCore
@objc protocol MathProtocol: JSExport {
    func add(_ lhs: Double, _ rhs: Double) -> Double
    func minus(_ lhs: Double, _ rhs: Double) -> Double
    func multiply(_ lhs: Double, _ rhs: Double) -> Double
    func divide(_ lhs: Double, _ rhs: Double) -> Double
}
class Math: NSObject, MathProtocol {
    func add(_ lhs: Double, _ rhs: Double) -> Double {
        return lhs + rhs
    }
    func minus(_ lhs: Double, _ rhs: Double) -> Double {
           return lhs - rhs
    }
    func multiply(_ lhs: Double, _ rhs: Double) -> Double {
        return lhs * rhs
    }
    func divide(_ lhs: Double, _ rhs: Double) -> Double {
        return lhs / rhs
    }
}
let context = JSContext()!
context.setObject(JSValue(double: 25, in: context), forKeyedSubscript: "a" as NSString)
context.setObject(JSValue(double: 5, in: context), forKeyedSubscript: "b" as NSString)
context.setObject(Math(), forKeyedSubscript: "math" as NSString)
print(context.evaluateScript("math.add(a, b)")!.toString()!) // 30
print(context.evaluateScript("math.minus(a, b)")!.toString()!) // 20
print(context.evaluateScript("math.multiply(a, b)")!.toString()!) // 125
print(context.evaluateScript("math.divide(a, b)")!.toString()!) // 5
上一篇下一篇

猜你喜欢

热点阅读