Skip to content

Instantly share code, notes, and snippets.

@foxicode
Last active May 12, 2020 21:26
Show Gist options
  • Select an option

  • Save foxicode/a02e479b131e3210ff7519d2fc494a42 to your computer and use it in GitHub Desktop.

Select an option

Save foxicode/a02e479b131e3210ff7519d2fc494a42 to your computer and use it in GitHub Desktop.
ViewController using JavaScript
import UIKit
import JavaScriptCore
class JSViewController: UIViewController {
@IBOutlet weak var vPluginContainer: UIView!
let jsContext = JSContext()!
var timer: Timer? = nil
let updateProperty: @convention(block) (Int, String, Any) -> Void = { tag, property, value in
NotificationCenter.default.post(name: NSNotification.Name("updateWidgetProperty"), object: (tag, property, value))
}
let addWidget: @convention(block) (String, [String: Any]) -> Void = { widgetName, widgetProperties in
print("Creating \(widgetName) with properties \(widgetProperties)")
switch widgetName {
case "Circle":
guard let x = widgetProperties["x"] as? Double,
let y = widgetProperties["y"] as? Double,
let r = widgetProperties["radius"] as? Double else {
break
}
let color = widgetProperties["color"] as? String ?? "#ffffff"
let tag = widgetProperties["tag"] as? Int ?? 0
let v = UIView(frame: CGRect(x: x - r, y: y - r, width: r * 2, height: r * 2))
v.layer.cornerRadius = CGFloat(r)
v.tag = tag
let uiColor = UIColor(hex: color) ?? .black
v.backgroundColor = uiColor
NotificationCenter.default.post(name: NSNotification.Name("addWidget"), object: v)
break
default:
print("Unknown widget - \(widgetName)")
}
}
@objc func addWidget(notification: NSNotification) {
guard let w = notification.object as? UIView else { return }
self.vPluginContainer.addSubview(w)
}
@objc func updateWidgetProperty(notification: NSNotification) {
guard let attr = notification.object as? (tag: Int, property: String, value: Any) else { return }
guard let w = vPluginContainer.viewWithTag(attr.tag) else { return }
switch attr.property {
case "color":
if let strValue = attr.value as? String,
let color = UIColor(hex: strValue) {
w.backgroundColor = color
}
default:
break
}
}
private func loadJavaScript() {
NotificationCenter.default.addObserver(self, selector: #selector(addWidget(notification:)), name: NSNotification.Name("addWidget"), object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(updateWidgetProperty(notification:)), name: NSNotification.Name("updateWidgetProperty"), object: nil)
// Add an exception handler.
jsContext.exceptionHandler = { _, exception in
print("JS Exception: ", exception?.toString() ?? "Unknown")
}
guard let jsSourcePath = Bundle.main.path(forResource: "jsPluginCode", ofType: "js") else {
print("JS file not found")
return
}
do {
let jsCode = try String(contentsOfFile: jsSourcePath)
jsContext.evaluateScript(jsCode)
let addWidgetObject = unsafeBitCast(self.addWidget, to: ViewController.self)
jsContext.setObject(addWidgetObject, forKeyedSubscript: "addWidget" as NSString)
let updatePropertyObject = unsafeBitCast(self.updateProperty, to: ViewController.self)
jsContext.setObject(updatePropertyObject, forKeyedSubscript: "updateProperty" as NSString)
}
catch {
print(error.localizedDescription)
}
}
@IBAction func runPlugin() {
loadJavaScript()
let startFunction = jsContext.objectForKeyedSubscript("start")
startFunction?.call(withArguments: [vPluginContainer.bounds.width, vPluginContainer.bounds.height])
timer = Timer.scheduledTimer(timeInterval: 0.01, target: self, selector: #selector(tick), userInfo: nil, repeats: true)
}
@objc func tick() {
let tickFunction = jsContext.objectForKeyedSubscript("tick")
tickFunction?.call(withArguments: [10.0])
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment