Skip to main content

iOS - UI Module

note

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.

Sample UIModule Implementation
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:

UIModuleViewController Implementation with Dismiss Response
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.