Developing custom Pega Mobile Client modules for the iOS platform
This tutorial describes how you can extend your custom mobile apps by using custom Pega® Mobile Client modules. You can develop custom modules in Objective-C or Swift and expose their functionality through the JavaScript API. They can enable features and functions that are available to native iOS applications in Pega Platform apps, for example allow the use of an embedded laser scanner to scan and recognize barcodes.
To learn what you can accomplish by extending the app, see Custom Pega Mobile Client modules.
For a technical introduction and definitions of terms used in this tutorial, see Custom Pega Mobile Client modules for the iOS platform.
To develop custom Pega Mobile Client modules for the iOS platform, complete the following tasks:
- Prerequisites
- Creating a custom module project
- Adding third-party dependencies
- Extending Pega Mobile Client with plug-in classes
- Extending Pega Mobile Client with extension classes
- Enabling the logger API
- Testing the custom module
- Packaging the custom module
Prerequisites
Before developing a custom module for iOS, do the following tasks:
- Download and configure the following items:
- Mac OS X 10.12.6 or later (the latest update is recommended)
- Xcode 9.0
- Java Runtime Environment (JRE) 8 x64
- Mobile provision profile prepared for the app
For more information, see Creating Development Provisioning Profiles on the Apple Developer Portal. - A valid development and distribution certificate
For more information, see the Certificate, Key, and Trust Services Programmer's Guide on the Apple Developer Portal.
- Obtain the distribution package for your intended platform. To do this, contact your Pegasystems Global Customer Support representative.
- Review the documentation in the doc folder of the distribution package to become familiar with the native custom module API and JavaScript API.
Known issues
Because of compatibility issues, you cannot use the networkActivityIndicatorVisible
property of the UIApplication
method to control the network activity indicator. Instead, use the PMNetworkActivityIndicator
class, which has been exposed in the Pega Mobile Client's native API. See the documentation provided in the distribution package.
Creating a custom module project
- Run Xcode, click New project, and select Cocoa Touch Framework.
- Click Product name field, enter a custom module name, for example, MyModule, and select your preferred programming language. . In the
- Click and save your project in the Modules folder of your distribution package.
- Browse to the Frameworks folder of the distribution package. Drag the PMBase.framework module to your project in Xcode.
- Accept the default settings in Xcode, and click .
- Navigate to the Build Settings tab in your project and set the Framework search paths parameter to $(PROJECT_DIR)/../../Frameworks.
Adding third-party dependencies
If you use third-party libraries that are written in Objective-C or Swift to extend Pega Mobile Client, you must add third-party dependencies to the project.
To add a dependency on a library project that includes source code, do the following steps:
- Drag the library project into Xcode to create a subproject of your custom module project.
- In the Project Navigator pane, select your custom module project to access its settings.
- Select your target. In the Build Phases tab, do the following steps:
- In the Target Dependency section, add the third-party library target.
- In the Link Binary With Libraries section, add the third-party library.
- Optional: In the Link Binary With Libraries section, add any system libraries that your third-party library requires.
To add a statically linked library that contains Objective-C code, do the following steps:
- Drag the library project into Xcode. Select Copy items if needed to add all the files to your project directory.
- In the Project Navigator pane, select your custom module project to access its settings.
- Select your target and do the following steps:
- In the Build Phases tab, in the the Link Binary With Libraries section, link the *.a library file to your targets.
- In the Build Settings tab, perform the following steps:
- In the Library Search Paths section, reference the directory.
- In the User Header Search Paths section, add the $(PROJECT_DIR) path, and select the Recursive checkbox.
- In the Other Linker Flags section, add the -ObjC flag.
- Optional: In the Link Binary With Libraries section of the Build Phases tab, add any system libraries that your third-party library requires.
To add a dynamically linked framework that contains the Objective-C or Swift code, do the following steps:
- Drag the framework into Xcode. Click Copy items if needed to add it to your project directory.
- In the Project Navigator pane, select your custom module project to access its settings.
- Select your target and do the following steps:
- In the Build Phases tab, in the Link Binary With Libraries section, link the framework to your targets.
- In the Build Settings tab, add the $(PROJECT_DIR) path in the Framework Search Paths section.
- In the Build Phases tab of your target, add a new Copy Files phase:
- In the Destination field, select Products Directory.
- Add the third-party framework in the area below the Destination field.
Extending Pega Mobile Client with plug-in classes
- To create the main plug-in class, do the following steps:
- In the Project Navigator pane, go to the MyModule folder.
- Click File > New File, and select Cocoa Touch Class.
- On the next screen, in the Class field, enter the name of the class. In the Subclass field, enter PMJavaScriptPlugin.
- In the Language field, select Objective-C or Swift, depending on the programming language that you use.
- Click , and then click .
- In the new class, import the PMBase module by using the
@import PMBase;
declaration. - If you selected Objective-C in the Language field, place the import statement in the header file. Otherwise, place it at the top of the Swift file.
- To implement the JavaScript side of the plug-in, do the following steps:
- In the Project Navigator pane, go to the Resources folder.
- Click File > New File to create a JavaScript file, for example, proximitySensor.js.
- Click Create. , and then click
- Edit the resource.
The name of the plug-in class that is used in theCreate code that is similar to the following example:
bridge.call
method must be the same as the one that was defined when the class was created.(function() { window.example = window.example || {}; window.example.ProximitySensor = { // The function makes a bridge call to native code and passes an object with a single function reference. // The callbacks is temporary and will be invalidated after first response is received. isCloseToTheUser: function (callback) { bridge.call('ProximitySensorExample', 'isCloseToTheUser', null, { 'onSuccess': callback }); } })();
- To return the JS code, implement the
provideJavaScriptWithCompletionHandler:
method (for Objective-C) orprovideJavaScript(completion:)
(for Swift) in your JavaScript code. See the following example of the Objective-C implementation:- The header file should contain code that is similar to the following example:
@import PMBase; @import UIKit; NS_ASSUME_NONNULL_BEGIN @interface ProximitySensorJSPlugin : PMJavaScriptPlugin #pragma mark - Called from JavaScript - (void) isCloseToTheUser:(nullable id)data withCallback:(nullable PMJavaScriptCallback *)callback; @end
- The implementation file should contain code that is similar to the following example:
#import "ProximitySensorJSPlugin.h" @interface ProximitySensorJSPlugin () @end @implementation ProximitySensorJSPlugin + (NSString *)name { return @"ProximitySensorExample"; } - (instancetype)initWithContext:(PMJavaScriptPluginContext *)context { if (self = [super initWithContext:context]) { // Do initialization here... } return self; } - (void)provideJavaScriptWithCompletionHandler:(void (^)(NSString *_Nonnull))completionHandler { NSString *scriptPath = [[NSBundle bundleForClass:[self class]] pathForResource:@"proximitySensor" ofType:@"js"] NSString *scriptCode = [NSString stringWithContentsOfFile: encoding:NSUTF8StringEncoding error:NULL]; completionHandler(scriptCode); } #pragma mark - Called from JavaScript - (void)isCloseToTheUser:(nullable id)data withCallback:(nullable PMJavaScriptCallback *)callback { dispatch_async(dispatch_get_main_queue(), ^{ BOOL proximityState = [[UIDevice currentDevice] proximityState]; [callback call:"onSuccess" passingData:@(proximityState)]; }); }
- The header file should contain code that is similar to the following example:
- Optional: To add any other resources, including configuration files, audio files, graphics, and videos, drag them to your project in Xcode, select Copy items if needed, and click .
Extending Pega Mobile Client with extension classes
- In the Project Navigator pane, go to the MyModule folder.
- Click File > New File, and select Cocoa Touch Class.
- On the next screen, in the Class field, enter the name of the class. In the Subclass field, enter PMApplicationPlugin.
- In the Language field, select Objective-C or Swift, depending on the programming language that you use.
- Click Create. , and then click
- In the new class, import the PMBase module by using the
@import PMBase;
declaration.If you selected Objective-C in the Language field, place the import statement in the header file. Otherwise, place it at the top of the Swift file. - Import and implement the
PMApplicationPlugin
protocol. See the following example of the Objective-C implementation.- The header file should contain code that is similar to the following example:
@import PMBase; @import UIKit; NS_ASSUME_NONNULL_BEGIN @interface ProximitySensorJSPlugin : PMApplicationPlugin @end NS_ASSUME_NONNULL_END
- The implementation file should contain code that is similar to the following example:
#import "ProximitySensorExtension.h" @implementation ProximitySensorExtension - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { [super application:application didFinishLaunchingWithOptions:launchOptions]; [[UIDevice currentDevice] setProximityMonitoringEnabled:YES]; return YES; } - (void)applicationDidEnterBackground:(UIApplication *)application { [super applicationDidEnterBackground:application]; [[UIDevice currentDevice] setProximityMonitoringEnabled:NO]; } - (void)applicationWillEnterForeground:(UIApplication *)application { [super applicationWillEnterForeground:application]; [[UIDevice currentDevice] setProximityMonitoringEnabled:YES]; } @end
- The header file should contain code that is similar to the following example:
Enabling the logger API
You can test your custom module by sending the log output to Xcode. You can use the Logger API, which is superior to the iOS NSLog macro. By using this API you can access the logs or set a logging level, and speed up logging. To use the Logger API in the custom module's native code, do the following steps:
- Import the PMBase module into your class.
- Use the following macros in your code:
PMLogError()
,PMLogWarn()
,PMLogInfo()
,PMLogDebug()
, andPMLogVerbose()
, which correspond to logging levels that are described in the Logger API reference.
Testing the custom module locally
- Drag the custom module project into the HybridContainer.xcworkspace as a subproject of the HybridContainer project.
- Open the HybridContainer target configuration, switch to the Build Phases tab, and add the module to the Target Dependencies, Link Binary with Libraries, and Embed Frameworks phases.
- Edit the HybridContainer-Info.plist file and change the value of
PMApplicationURL
parameter to your intended instance of Pega Platform, for example,http://test.server.com:8243/prweb/
. - Click . The Pega Mobile Client starts on a connected device.
Packaging the custom module
When your custom module is ready and has been tested, prepare it for packaging within a .zip file, for example custom-module-assets.zip file. To obtain a sample custom module package that you can rename and use as a template for your package, right-click and save the following link:
custom-module-assets.zip (0.83 MB)
- Set the Active Scheme in Xcode to Generic iOS Device.
- Click > to compile your custom module.
- To find the custom module binary, do the following steps:
- In the Products directory of the Project Navigator pane, right-click the framework.
- Click . The file name is MyModule.framework.
- If you are using the sample custom-module-assets.zip file, remove the default contents of the modules-ios folder.
- Copy the module binary to the modules-ios folder that is in the custom-module-assets.zip file.
- Upload the custom-module-assets.zip file with your custom module to the Pega Platform. For more information, see Uploading custom modules.