iOS - Method Module
To call a MethodModule, a Tecton Caliper extension is required. Please refer to the
Caliper guides to get started.
The MethodModule interface provides the ability to create native methods which can be
called from Q2MobileCore through Tecton. The invoked Tecton method will execute the native
code written inside the type implementing method module.
This native code is able to execute native frameworks, third-party SDKs and return a response back to the Tecton method call.
MethodModule now also supports a typed request pattern for cross-module data exchange.
This complements the existing Tecton method invocation pattern and is useful when
multiple modules can respond to the same supported request type.
Selector-Based Method Implementation
Implementing a MethodModule is straightforward—create a class inherited from NSObject
and conforming to the MethodModule protocol requirements.
import Q2ModuleInterfaces
class CustomMethodModule: NSObject, MethodModule {
var moduleInvocationData: ModuleInvocationData!
var moduleDelegate: ModuleDelegate?
var moduleDataSource: ModuleDataSource?
// Example: Javascript Method to Native Method (@objc)
@objc func yourJSMethodName(data: MethodModuleData, callback: MethodModuleCallback) {
let parameterValue = data.data["parameterName"]?.stringValue ?? "unknown"
let response = MethodModuleResponse(withResponse: parameterValue)
callback.completion(response)
}
// Example: Javascript Method to retrieve token (@objc)
@objc func getQ2Token(data: MethodModuleData, callback: MethodModuleCallback) {
let token = moduleDataSource?.user?.token ?? "nil"
let response = MethodModuleResponse(withResponse: token)
callback.completion(response)
}
}
Use this pattern when your module exposes one or more native methods that are called directly from Tecton using a module identifier and method name.
Typed Request Handling
In 26.3.0, MethodModule adds an async request-handling API:
import Q2ModuleInterfaces
class CustomMethodModule: NSObject, MethodModule {
var moduleInvocationData: ModuleInvocationData!
var moduleDelegate: ModuleDelegate?
var moduleDataSource: ModuleDataSource?
func handleRequest(_ request: MethodRequest) async -> [String: JSONValue]? {
switch request {
case .oauthAuthorizationParams(let context):
return [
"queryParamKey": .string("custom_session"),
"queryParamVal": .string("abc-123"),
"issuerUrl": .string(context?.issuerURL?.absoluteString ?? "")
]
}
}
}
Use this pattern when:
- multiple modules may respond to the same request type
- the host app or another module needs aggregated responses
- typed JSON payloads are preferred over untyped dictionaries
Partners do not define arbitrary custom MethodRequest cases. The available request
types are defined by Q2ModuleInterfaces, and modules can choose whether or not to
respond to those supported requests.
Supported Request Types
As of 26.3.0, Q2ModuleInterfaces includes one supported request type:
MethodRequest.oauthAuthorizationParams(context:)
This request allows modules to contribute OAuth authorization parameters, such as custom query-string values.
Starting in Mobile SDK iOS 26.4.0, the issuerUrl value in the request context must be
a valid http or https URL string without whitespace. Invalid values are ignored and
resolved as nil.
Selector-Based Method Invocation
To invoke selector-based native methods defined in your native method module, use the
Tecton callMethod capability in your online extension.
tecton.actions
.callMethod('moduleIdentifier', 'methodName', { parameterName: 'parameterValue' })
.then(response => {
//was successful at calling method
})
.catch(error => {
//could not call method
});
moduleIdentifieris configured by Q2 on module creation.methodNameis the name of the @objc method defined by your module. You can define multiple methods.
Example: A module called Math can have multiple methods, like: sum, multiply, divide etc.
Aggregated Typed Request Usage
Typed requests are not exposed as named Tecton methods. Instead, the Mobile SDK collects
responses from loaded method modules that support the requested MethodRequest.
As a module developer, you will typically interact with this pattern in one of two ways:
- implement
handleRequest(_:)so your module can contribute data for a supported request - call
ModuleDataSource.executeMethodRequest(_:)when your module needs aggregated responses from other loaded method modules
Example:
let responses = await moduleDataSource?.executeMethodRequest(
.oauthAuthorizationParams(
context: OAuthContext(issuerURL: URL(string: "https://example.okta.com/oauth2/default"))
)
)
for response in responses ?? [] {
print("Module: \(response.moduleIdentifier)")
print("Data: \(response.data)")
}
Each response includes:
moduleIdentifierdataas[String: JSONValue]
Choosing a Pattern
- Use selector-based
@objcmethods when Tecton needs to invoke a specific native method directly. - Use
handleRequest(_:)when the request represents shared data that can be returned by more than one module.