iOS - UI Module
To present native user interfaces, a proper implementation of the UIModule
protocol is
required. SwiftUI code is supported if it's wrapped in a UIViewController before it is
returned to the Q2MobileCore. :::
The UIModule
interface is used when creating a module that requires presenting native
user interfaces. The implementation should be responsible for providing a
UIViewController, which is presented using a specific modal presentation style by
Q2MobileCore.
Implementation
Implementing a UIModule
is straightforward—create an NSObject class conforming to the
UIModule protocol requirements.
import Q2ModuleInterfaces
class CustomUIModule: NSObject, UIModule {
var moduleDelegate: ModuleDelegate?
var moduleDataSource: ModuleDataSource?
/// Provide a view controller which needs to be presented by Q2 Mobile Core.
func viewControllerToPresent(for identifier: String, withAppData appData: ModuleInvocationData) async -> UIViewController? {
return nil
}
/// Notifies the module by Q2 Mobile Core that it has finished presenting module.
func didOpen(_ identifier: String) {
// no-op
}
/// Informs Q2 Mobile Core that whether user is able to dismiss the module or not.
func shouldLeavePage(decisionHandler: @escaping (LeaveOrStayOnPage) -> Void) {
decisionHandler(.leave)
}
}
Presentation
To present UI provided by your module by Q2MobileCore, use Tecton - openModule capability in your online extension.
tecton.actions
.openModule('moduleIdentifier', '{"key": "value"}')
.then(response => {
// was successful at opening module
})
.catch(error => {
// could not open module
});
moduleIdentifier
is configured by Q2 on module creation.data
is in JSON form to pass to the type implementing UI Module.
Dismiss Response
If you want to provide dismiss response back to Tecton layer, inherit your view controller from UIModuleViewController.
Assume you have a dismiss button tied with the following dismiss method in a view controller which is inherited from UIModuleViewController:
final class CustomUIViewController: UIModuleViewController {
self.navigationItem.leftBarButtonItem = UIBarButtonItem(
title: "Data",
style: .plain,
target: self,
action: #selector(dismissViewWithData)
)
@objc func dismissViewWithData() {
let date = Date().description
let dismissResponse = UIModuleDismissResponse(data: date)
dismissWithResponse(dismissResponse)
}
}
On dismissal, the current date would be provided as Data back to the Tecton layer which has invoked this UIModule.