Implement front call modules for GMI
Custom front call modules for the iOS front-end are implemented by using the API for GMI front calls in Objective-C.
GMI custom front call basics
In order to extend the GMI with your own front calls, you must be familiar with Objective-C programming, and if you want to interface with iOS Apps, have a knowledge of the iOS API.
The API for GMI front calls is based on the FrontCall class and the
FrontCallHelper and FunctionCall protocols. You can find these in
the file frontcall.h in the in the $FGLDIR/include/gmi
diretory.
To implement custom front calls, write a class which extends FrontCall and
implements the “moduleName” and “execute:retCount:params” methods
as well as the “initWithFunctionModuleHelper:” initializer.
- Import the 
frontcall.hheader file in your source. - Define an interface (
MyFrontCall) which extendsFrontCall. - Create the class (
MyFrontCall) which implements this interface:- Implement the 
- (instancetype) initWithFunctionModuleHelper:(id)aHelperinitializer, calling[superinitWithFunctionModuleHelper:aHelper]to pass theFrontCallHelperto the base implementation. - Implement the 
- (NSString*) moduleNamemethod, returning the name of the front call module. - Implement the 
- (void)execute:(NSString)name retCount:(int)retCount params:(NSArray)paramsmethod, defining the body of your front calls. See below for details about theexecutemethod. 
 - Implement the 
 
API to implement custom front calls in GMI
To get parameters passed from the Genero program to the front call, and return values from
        the front call to the Genero program, use the following macros and methods of the
          FrontCall class:
| Macro / Method | Description | 
|---|---|
                
               | 
              
                 Checks that the number of parameters passed by the Genero program equals count. This macro will raise an error in the Genero program if not enough parameters were passed.  | 
            
                
               | 
              
                 Get the string parameter passed to the front call, at the given position. If the
                  parameters are of a different type, use the   | 
            
                
               | 
              
                 Get the int parameter passed to the front call, at the given position.  | 
            
 | 
 Ends the front call by returning one integer to Genero.  | 
 | 
 Ends the front call by returning one double to Genero.  | 
 | 
 Ends the front call by returning one string to Genero.  | 
                
               | 
              
                 Initiate setting multiple result values. Must be followed by   | 
            
                
               | 
              
                 Add an integer to the list of results returned. To be used after a   | 
            
                
               | 
              
                 Add a double to the list of results returned. To be used after a   | 
            
                
               | 
              
                 Add a string to the list of results returned. To be used after a   | 
            
 | 
 Finalize the setting of multiple result values and return the results to the Genero program, with front call error code zero (indicating success).  | 
                
               | 
              
                 Ends the front call without returning any value to Genero, indicating that the front call execution was successful.  | 
            
                
               | 
              
                 Ends the front call with a specific front call error code defined in FCErrorCode enum in frontcall.h, to indicate that front call execution failed, typically because of invalid parameters or invalid function name.  | 
            
                
               | 
              
                 Ends the front call with front call return code -4 (maps to BDL error -6333), and a
                  user-defined error message, that can be read with   | 
            
                
               | 
              
                 To be called at the end of the  If the  For example, if your front call opens a message box, the   | 
            
Calling the custom front call from BDL
In the Genero program, use the ui.Interface.frontCall() API to call the front-end function.
        This method takes the front call module name as first parameter and the front call function
        name as second parameter.
The front call module name is defined by the string value returned from the
          -(NSString * ) moduleName* method of your front call implementation, and
        the front call function name is passed to the execute method you
        implemented as first parameter (name).
For example, if you implement the following class:
#import <gmi/frontcall.h>
...
@interface MyFrontCall : FrontCall
   ...
@end
@class MyFrontCall
-(instancetype) initWithFunctionModuleHelper:(id)aHelper
{
   if (self = [superinitWithFunctionModuleHelper:aHelper]) {
      ...
   }
   return self;
}
-(NSString*) moduleName{
   return @"MyModule";
}
-(void)execute:(NSString)name
               retCount:(int)retCount
               params:(NSArray)params
{
   [super execute:name retCount:retCount params:params];
   if ([[name lowercaseString]isEqualToString:@"myfrontcall"]) {
      ...
      The Genero program code must pass the module name "MyModule" as front call
        module name and the class name "MyFrontCall" as front call function
        name:
CALL ui.Interface.frontCall("MyModule", "MyFrontCall", ["John DOE"],[msg])
    Custom front call implementation details (execute method)
FrontCall class, right
        at the top of the execute
        method:   [super execute:name retCount:retCount params:params];The execute method must check the name of the front call function passed
        as parameter, to perform the expected code. This is the function name passed to the
          ui.Interface.frontCall() call in the Genero program:
   if([[name lowercaseString] isEqualToString:@"myfunction"]) {Implement
        the body of the front call function in the if() block as follows:assert() line, to make sure that the number of return values
        match:      assert(retCount == 2);In order to get the parameters passed from the Genero program, use the FC_* macros in the body of your front call function.
FC_REQUIRED_PARAMS(count)
        macro:      FC_REQUIRED_PARAMS(3);
      ...FC_PARAM(index) or
            FC_PARAM_INT(index) macros, which return a
          NSString* and an int respectively. If needed, use the
          doubleValue, floatValue and
          integerValue methods on NSString or a
          NSScanner, to convert the parameter to the expected
        type:      NSString * info = FC_PARAM(0);
      int v1 = [FC_PARAM(1) integerValue];
      double v2 = [FC_PARAM(2) doubleValue];Implement the actual code of the front call.
intResult:value, if a single value must be returned
        to the Genero program. If more than one value must be returned, build a return set with the
          startResult, add*Result and endResult
        methods:    [self startResult];
    [self addIntResult:isIpad];
    [self addIntResult:canLocate];
    [self endResult];UIAlertController or
displays a customer UIViewController), call the willSetResultLater
method of the FrontCall class, to avoid having the control flow returned to the
Genero program upon exit of the execute
method:    [self willSetResultLater];Additionally, if you call the willSetResultLater method, you need to call one of
the result methods like stringResult at a later time.
Deploying the custom front call
The complied Objective-C classes must be included in the iOS app build process.
The same app building rules apply for custom front calls as for C extensions.
See Building iOS apps with Genero for more details.
Example
In this example, the ExtensionFrontCall class implements two front calls:
        "isipad" and "logindialog".
We start by defining the interface for the custom front call module:
@interface ExtensionFrontCall : FrontCall<UIAlertViewDelegate>
@end
      The ExtensionFrontCall class extends FrontCall, and
        implements the UIAlertViewDelegate protocol which is used by the
        "logindialog" front call.
@implementation ExtensionFrontCall
-(instancetype) initWithFunctionModuleHelper:(id)aHelper
{
   if (self = [superinitWithFunctionModuleHelper:aHelper]) {
   }
   return self;
}
-(NSString*) moduleName{
   return @"ExtensionFrontCall";
}
-(void)execute:(NSString)name retCount:(int)retCount params:(NSArray)params {
   [super execute:name retCount:retCount params:params];
   ...
}
...
@endWe use the standard initializer which will be called by GMI on start-up and define
"ExtensionFrontCall" as module name by returning it from the
moduleName method.
We also start the implementation of the execute method by calling the super
method.
isipad front call exampleif ([[name lowercaseString] isEqualToString:@“isipad”]) {
    assert(retCount == 1);
    BOOL isIpad = UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad;
    [self startResult];
    [self addIntResult:isIpad];
    [self endResult];
}After checking that only one return parameter was defined in Genero, the code identifies the
platform with the UI_USER_INTERFACE_IDIOM() API and stores the result in the
isIpad variable.
The next three lines return the result value to Genero, by starting a result block with
          startResult, adding an int to the return set with
          addIntResult, and finally calling endResult to send the
        result to the Genero program.
The same behavior can be achieved with a single line: [self intResult:isIpad];,
        since we only return one result value.
isIPad front call as
follows:DEFINE res INTEGER
CALL ui.Interface.frontCall( "ExtensionFrontCall", "isipad", [ ], [res] )The
logindialog front call exampleif([[name lowercaseString] isEqualToString:@“logindialog”]) {
    assert(retCount == 2);
    FC_REQUIRED_PARAMS(2);
    NSString *title = FC_PARAM(0);
    NSString *message = FC_PARAM(1);
    UIAlertView *alert = [[UIAlertView alloc]
      initWithTitle:title
      message:message
      delegate:self
      cancelButtonTitle:NSLocalizedString(@"Cancel",@"Cancel")
      otherButtonTitles:NSLocalizedString(@"OK",@"OK"),nil];
    alert.alertViewStyle = UIAlertViewStyleLoginAndPasswordInput;
    [alert show];
    [self willSetResultLater];
}We first check that two result values were set in Genero and that two parameters were supplied to the front call.
Then we use the FC_PARAM macro to fetch the parameters and assign them to
NSStrings.
Then we allocate and initialize an UIAlertView with the given message and title
and set the alertViewStyle to
"UIAlertViewStyleLoginAndPasswordInput", so that one plain text field and one
password field will be displayed on the alert.
In the initWithTitle call we also set "self" as the delegate of
the alert so that we receive callbacks after user input (we had added the
UIAlertViewDelegate protocol to our ExtensionFrontCall interface
definition).
Finally, we call willSetResultLater, to keep the control flow in iOS. If we
don’t call this function, GMI concludes the front call was not handled by the
execute function (as none of the xxxResult functions was called
inside), and the front call will fail with a “Frontcall not found” error message.
ExtensionFrontCall class implements the
          alertView:didDismissWithButtonIndex: method from the
          UIAlertViewDelegate
        protocol:pragma mark UIAlertViewDelegate(void)
alertView:(UIAlertView *)alertViewdidDismissWithButtonIndex:(NSInteger)buttonIndex {
   [self startResult];
   if (buttonIndex != alertView.cancelButtonIndex) {
      [self addStringResult:[alertViewtextFieldAtIndex:0].text];
      [self addStringResult:[alertViewtextFieldAtIndex:1].text];
   } else {
      [self addStringResult:nil];
      [self addStringResult:nil];
   }
   [self endResult];
}This method is called after the user has tapped on one of the buttons and the view has been
        dismissed. Inside this method, we first call startResult to enable adding
        more than one return value.
If the tapped button was not the Cancel button, we add the values of the log-in and password
fields as strings to the results and then call endResult to return the control flow
to the Genero program.
DEFINE ul, up STRING
CALL ui.Interface.frontCall( "ExtensionFrontCall", "logindialog",
                             ["MyApp","User login"],
                             [un, up] )
IF up IS NULL THEN
   ERROR "Login canceled"
   EXIT PROGRAM
END IF