Skip to main content

CustomCommand Interface

The process of implementing API interfaces using CustomCommand is as follows:

1 Inject CustomeCommand listener into the host​

let gameHandle: RuntimeGameHandle
gameHandle.setCustomCommandListener("sampleLogin") { request, handle in
// validate params, returns error when params are invalid
guard let username = request["username"] as? String else {
handle.fail(errorCode: 20001, errorMsg: "invalid username")
return
}
guard let nonce = request["nonce"] as? Int32 else {
handle.fail(errorCode: 20001, errorMsg: "invalid nonce")
return
}
guard let data = request["data"] as? Data else {
handle.fail(errorCode: 20001, errorMsg: "invalid cert")
return
}

// simulate async requests
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
handle.success(result: ["username": username + "_login", "age": 18, "data": data, "nonce": nonce])
}
}

2 Implement Custom Listening​

let gameHandle: RuntimeGameHandle
gameHandle.setCustomCommandListener(CustomCommandListener())

class CustomCommandListener: TJCustomCommandListener {
func onCustomCommand(command: String, request: NSDictionary, handle: TJCustomCommandHandle) {
switch command {
case "sampleLogin":
// validate params, returns error when params are invalid
guard let username = request["username"] as? String else {
handle.fail(errorCode: 20001, errorMsg: "invalid username")
return
}
guard let nonce = request["nonce"] as? Int32 else {
handle.fail(errorCode: 20001, errorMsg: "invalid nonce")
return
}
guard let data = request["data"] as? Data else {
handle.fail(errorCode: 20001, errorMsg: "invalid cert")
return
}

// simulate async requests
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
handle.success(result: ["username": username + "_login", "age": 18, "data": data, "nonce": nonce])
}

default:
handle.fail(errorCode: 20000, errorMsg: "command not found")
}
}
}

3 Implement API interfaces in JavaScript​

In JavaScript, you can access tj and cusObj variables. tj is used to call and add APIs, and cusObj is used to store functions for internal use.

tj.customCommand​

Call the corresponding Swift method via tj.customCommand.

tj.sampleLogin = function (obj) {
tj.customCommand("sampleLogin", obj);
};

The obj parameter contains not only the corresponding interface parameters but also interface callbacks. The callback parameters are defined as follows:

Parameter NameTypeRequiredDescription
successFunctionYesCallback function for successful interface call
failFunctionNoCallback function for interface call failure
completeFunctionNoCallback function for the end of interface call (executed upon both successful and failed calls)

API Call Example

tj.sampleLogin({
username: "test",
nonce: 123,
data: data,
success: function (res) {
console.log(
`sampleLogin: user=${res.username}, age=${res.age}, nonce=${res.nonce}`,
);
},
fail: function (res) {
console.error(`login fail: ${res.errorCode}, ${res.errorMsg}`);
},
});

tj.customCommandSync​

Synchronous calls to the swift interface are implemented through tj.customCommandSync.

API Call Example

tj.sampleLoginSync = function (obj) {
return tj.customCommandSync("sampleLogin", obj);
};

4 Pass in custom initialization JavaScript​

options[TJConstants.CUSTOM_SCRIPT_FILES] = getCustomScriptFiles()
options[TJConstants.CUSTOM_SCRIPT_CONTENTS] = getCustomScripts()

func getCustomScriptFiles() -> [String] {
var files: [String] = []

if let authJsUrl = Bundle(for: type(of: self)).url(
forResource: "auth",
withExtension: "js") {
files.append(authJsUrl.path)
}

if let adJsUrl = Bundle(for: type(of: self)).url(
forResource: "ad",
withExtension: "js") {
files.append(adJsUrl.path)
}

return files
}

func getCustomScripts() -> [String] {
return [
"""
tj.sampleLogin = function(obj) {
tj.customCommand("sampleLogin", obj);
}
"""
]
}

5 Execute JavaScript during runtime​

When the host is running, you can call RuntimeHandle.runCustomScript to execute JavaScript code. The code can access the tj and cusObj variables.

func runCustomJavascriptObject() {

let script = """
console.log("runCustomJavascript");
return {name: "john", age: 18, pass: true, score: [40.2, 40, 70.2]};
"""

gameHandle.runCustomScript(script) { result, error in
if let error = error {
print("error: \(error)")
} else {
let result = (result as? NSDictionary)!
print("name: \((result["name"] as? String)!)")
print("age: \((result["age"] as? Int32)!)")
print("pass: \((result["pass"] as? Bool)!)")
let score = result["score"] as! [Double]
print("score: \(score[0]), \(score[1]), \(score[2])")
}
}
}