NFI Swift - JavaScript API Reference

Creating Objects


var obj = new MyClass();              // standard init
var obj = new MyClass("hello", 42);   // parameterised init
var obj = MyClass.jsnew("abc");       // use for failable init? — returns null on failure

Calling Methods


obj.methodName(arg1, arg2);

Swift argument labels are not preserved. Pass arguments positionally, following the order in which they are declared.

// Swift:  func move(to point: Point, duration: Double) -> Bool
// JS: obj.move(point, 1.5);

Properties


// Read
var val = obj.propertyName;

// Write
obj.propertyName = newValue;

Assignments to read-only properties (Swift { get }) are silently ignored.

Static Methods and Properties


var result = MyClass.staticMethod(arg);
var val    = MyClass.staticProperty;
MyClass.staticProperty = newValue;

Singletons


var shared = MyClass.shared;   // access the shared instance
shared.doSomething();

Method Chaining

Methods that return Self are supported naturally.



var result = builder.select("*").from("users").where("age > 18").limit(5).build();

Subscripts


obj["key"]       // String-keyed subscript get
obj["key"] = v   // String-keyed subscript set (if read-write)
obj[0]           // Int-keyed subscript get

Type Mapping

Swift Type JavaScript Value
Int, Int32, UInt, Int64 number
Double, Float, CGFloat number
Bool boolean
String string
Character single-character string
Data Array of byte numbers [202, 254, …]
URL string (the URL's absolute string)
Date number (milliseconds since epoch)
Error string (localised description) or an enum ref
[T] (Array) JS Array
[K:V] (Dictionary) JS Object / dict
Set<T> JS Array (order not guaranteed)
Optional<T> — .none null
Named tuple (a: T, b: U) JS Object { a: …, b: … }
Class instance Wrapped JS object with prototype methods
Struct instance Wrapped JS object with prototype methods
UIColor [r, g, b, a] (Doubles 0.0–1.0)
CGRect { x, y, width, height }
CGPoint { x, y }
CGSize { width, height }

Supported Swift Features

Primitives and Strings

The following Swift types are supported as parameter and return types: Int, Int32, UInt, Double, Float, CGFloat), Bool, String, Character, Data, URL, Date, and Error.

Optionals

Optional variants of all supported types are also supported. nil is mapped to null in JavaScript, and null can be passed from JavaScript for optional parameters.

Collections

[String], [Int], [Double], [Bool], [Data], [URL], [String:Any], Set<String>, nested arrays, and nested dictionaries.

Classes and Inheritance

Single and multi-level class inheritance. Subclass instances retain access to all superclass methods.

Structs

Structs with stored properties and instance methods. Properties are read/write from JS.

Enums

Pattern Supported
Raw-value enum (String, Int) obj.rawValue, MyEnum.init_rawValue("val")
Instance methods on enum cases obj.methodName()
Associated-value enum describe() and label computed property

Closures and Callbacks

Closures as method parameters, including completion handlers:



// Swift
func compute(_ a: Int, _ b: Int, using op: (Int, Int) -> Int) -> Int

// JS
var result = obj.compute(10, 5, function(a, b) { return a + b; });

Completion handlers (async callbacks):


// Swift
func fetchData(completion: (String?, Error?) -> Void)

// JS
obj.fetchData(function(value, error) {
    if (error) { /* handle */ }
    kony.print(value);
});

Async / Concurrency

async methods are supported via a completion-handler bridge pattern. The result is delivered to a JS callback; the synchronous return from JS will be null.


// Sync return is null — use the callback
obj.fetchMessage(function(result, err) {
    kony.print("result:", result);
});

Throwing Methods

Swift throws is bridged via a Result-style callback or by checking the returned error:


var val = obj.parsePositive(5);    // returns value on success
var val = obj.parsePositive(-1);   // returns null; error accessible if needed

Protocols and Protocol Conformance

Classes conforming to protocols expose all protocol methods. Methods provided by protocol extensions (default implementations) are also available.


var g = new Greeter("Alice");
g.greet();      // own method
g.farewell();   // from protocol extension default

Method Overloading

Overloads with different parameter counts are dispatched correctly. Overloads that differ only by Int vs Double (same arity) fall back to Int (known limitation).

Static Factory Methods


var v = Vehicle.create("Tesla", 2023, "Electric", 320);
var g = Person.guest();

Named Tuple Returns

Named tuples are returned as JS dictionaries:


var stats = s.analyze([1, 2, 3, 4, 5]);
kony.print(stats.min, stats.max, stats.average, stats.count);

var parts = s.partition([1,5,3,8,2], 5);
kony.print(parts.below);   // array of values < 5
kony.print(parts.above);   // array of values >= 5

Computed Properties

Computed get-only and get/set properties on classes and structs are accessible as regular JS properties.

inout Parameters

Void methods with inout parameters return a JS dict of all mutated values keyed by the Swift parameter name:


// Swift
public func swap(_ a: inout Int, _ b: inout Int)
public func clamp(_ value: inout Double, lo: Double, hi: Double)
var result = helper.swap(3, 7);
kony.print(result.a);   // 7
kony.print(result.b);   // 3

var c = helper.clamp(15.0, 0.0, 10.0);
kony.print(c.value);    // 10

Non-void inout methods return their explicit return value as normal (the Swift return value, not a dict).

willSet / didSet Property Observers

Property observers fire on the Swift side automatically when the property is set via JS. Read the side-effect properties back after the assignment:


store.value = 10;
kony.print(store.changeCount);  // 1 (incremented by willSet)
kony.print(store.lastValue);    // 0 (captured by didSet)

Type Aliases

typealias declarations in Swift source are fully resolved by the tool. Use type aliases exactly as you would the underlying type — aliases for closures, dicts, arrays, and named tuples all work transparently:


// Swift
public typealias IntMapper  = (Int) -> Int
public typealias JSONDict   = [String: Any]
var result = demo.transform([1, 2, 3, 4], function(n) { return n * 2; });
var info   = demo.describe("score", 99);  // { key: "score", value: 99, type: "int" }

@discardableResult

Swift methods marked @discardableResult are dispatched normally, and their return values remain available in JS whether used or discarded:


var count = logger.log("event");   // use the return value
logger.log("event");               // discard it — both work

Protocol as Method Parameter Type

Pass any wrapped instance whose Swift class conforms to the protocol — no special JS syntax required:


// Swift
public func getValue(_ item: Measurable) -> Double
var len = new Length(30.0);
var wt  = new Weight(5.0);
kony.print(comparator.getValue(len));    // 30
kony.print(comparator.compare(len, wt)); // 1

Extension Methods on Known Classes

Methods added to a class via extension MyClass { } in the same Swift module are fully dispatched. Call them on any instance just like regular methods:

var root = new TreeNode("root");
// extension methods available alongside regular methods
kony.print(root.allValues());    // ["root", "child1", …]
kony.print(root.size());         // total node count
kony.print(root.contains("x"));  // true/false

Recursive / Tree Data Structures

Classes that reference themselves (e.g. tree nodes) work correctly. Arrays of class instances are fully wrapped with prototype access.

var root = new TreeNode("root");
var child = new TreeNode("child");
root.addChild(child);
var children = root.children();  // returns array of TreeNode objects
children[0].value;               // "child"

Multiple System Framework Imports

A single Swift class file can import any number of Apple system frameworks.

Third-Party xcframework Dependencies

If your Swift framework imports another xcframework (e.g. a logging or analytics SDK), place those dependency xcframeworks in a folder and set SwiftDependencies in config.plist. The tool will import and link them automatically.

Limitations

# What doesn't work Workaround
L1 Same-arity Int vs Double overloads stringify(5.5) routes to the Int variant Use distinct method names
L2 new ClassName() for failable init?** — returns a zombie object instead of null when given bad input Use ClassName.jsnew(arg) which returns null correctly
L3 Generic types — class Box<T> is skipped entirely Provide concrete wrapper types (e.g. class StringBox)
L4 Nested types — Outer.Inner is not parsed Hoist inner types to module level
L5 Operator overloads — static func +(lhs:rhs:) cannot be called Provide a named wrapper (func add(_ a: T, _ b: T))
L6 Unnamed tuple returns — (Int, String) Use named tuples: (value: Int, label: String)
L7 inout void methods** — JS gets a dict {paramName: value} per mutated arg, not mutation of the original variable (JS has no pass-by-reference) Read mutated values from the returned dict: var r = obj.swap(a, b); r.a; r.b
L8 Object memory — Swift objects stored in the JS bridge are never automatically released Call __nfi_swift_release(ref) manually when done with an object
L9 **Pure async/await return** — calling an async method synchronously returns null Bridge with a completion handler parameter