Objective-C Language-Specific Library

The Objective-C IC library provides an Objective-C implementation to communicate with IC servers via the REST interface. The library is largely a one-to-one pass-through to the REST service. It provides a collection of objects that represent resources and objects made available by the API. With the Objective-C layer, you don't have to know the exact URLs for things and it takes the guesswork out of supplying the right data object for each resource.

This topic contains the following sections:

Overview

The library is provided as header and implementation files to be included in your project. Each namespace from the REST API is imitated using class name prefixes in order to provide uniqueness and discoverability via code completion. All resources are prefixed with 'ICWSResources' and all data contracts are prefixed with 'ININ'. A resource will contain one or more methods, such as createConnection:withCompletionBlock:. The first parameter to the method will always be a request object whose class is prefixed with 'ICWSRequests'. The request object will encapsulate any URL template token values, headers, query options, as well as the request representation for the resource method. The second parameter is a completion block which allows you to do something with the response when it comes.

On the result of the REST call, the completion block you provide will be handed back the NSHTTPURLResponse for the response, an NSData for the response data, and an NSError in case the request could not be completed. In the NSHTTPURLResponse object you can access the status code result and any headers that were returned in the result. The NSData object can be deserialized into the appropriate data contract. It is important to note that the NSError object is only used when the request was not completed, for example the request timing out.

Connecting

The first thing you will need is a class which adopts the ICWSResourceDelegate protocol. An example is given with the ICWSResourceHelper class. Once you have an ICWSResourceDelegate, you can construct any resource objects from the library.

The ICWSResourcesConnectionConnection object has a createConnection:withCompletionBlock: method that will create the connection to the IC server. This method requires the ICWSRequestsConnectionConnectionCreateConnection object which takes the requested language to set in the request header as well as a subclass of ININConnectionBaseAuthConnectionRequestSettings. This object will contain the essential connection parameters needed for that authentication type, such as the user name and password for IC Authentication.

Messaging

The ICWSResourcesMessagingMessages object is used to retrieve messages from the IC server. The messages are events that are raised on the IC server, such as a status changing or an interaction being added. If using short-polling, the messages are queued on the server and should be retrieved on a regular interval as the queue will start filling up again as soon as a batch of messages is retrieved. If using server-sent events, the messages are not queued on the server, and are sent as they occur. The client application should check the messaging feature version to determine if server-sent events is supported on the server. Server sent events are supported with messaging version 2 and higher. See the Versioning page for further information on handling versioning.

If using short-polling, calling the resource object's getMessages:withCompletionBlock: method will request the batch of messages from the server. Like other resource method calls, the second parameter is a completion block which will be handed back the response information. If you receive a 200 status code from the call, the response JSON will contain an array of dictionaries which can be deserialized to ININMessagingMessage objects. The array may be empty.

Putting It Together: Simple Example

    //
    //  ViewController.h
    //  ExampleICWS
    //
    //  Created by ININ on 1/4/16.
    //  Copyright © 2016 Genesys. All rights reserved.
    //

    #import <UIKit/UIKit.h>

    @interface ViewController : UIViewController


    @end
                
    //
    //  ViewController.m
    //  ExampleICWS
    //
    //  Created by ININ on 1/4/16.
    //  Copyright © 2016 Genesys. All rights reserved.
    //

    #import "ViewController.h"
    #import "ICWSRequestBuilder.h"
    #import "ICWSRequestDispatcher.h"
    #import "ICWSResourceHelper.h"

    @interface ViewController ()
    @property (nonatomic, strong) ICWSResourceHelper *resourceHelper;
    @end

    @implementation ViewController

    - (void)viewDidLoad {
        [super viewDidLoad];
        
        // Prepare the ICWSResourceDelegate to pass into each resource object.
        ICWSRequestBuilder *requestBuilder = [[ICWSRequestBuilder alloc] init];
        ICWSRequestDispatcher *requestDispatcher = [[ICWSRequestDispatcher alloc] init];
        
        NSString *serverBaseUri = @"https://HostServerName:HostPort";
        self.resourceHelper = [[ICWSResourceHelper alloc] initWithServiceEndpoint:serverBaseUri requestBuilder:requestBuilder andRequestDispatcher:requestDispatcher];
        
        ININConnectionIcAuthConnectionRequestSettings *icAuth = [[ININConnectionIcAuthConnectionRequestSettings alloc] init];
        icAuth.userID = @"userID";
        icAuth.password = @"password";
        icAuth.applicationName = @"Example";
        
        ICWSResourcesConnectionConnection *connectionResource = [[ICWSResourcesConnectionConnection alloc] initWithDelegate:self.resourceHelper];
        ICWSRequestsConnectionConnectionCreateConnection *connectRequest = [[ICWSRequestsConnectionConnectionCreateConnection alloc] init];
        connectRequest.acceptLanguage = @"en-US";
        connectRequest.baseAuthConnectionRequestSettings = icAuth;
        connectRequest.include = @"features";
        
        [connectionResource createConnection:connectRequest withCompletionBlock:^(NSHTTPURLResponse *httpResponse, NSData *responseData, NSError *error) {
            NSError *parseError = nil;
            NSDictionary *result = [NSJSONSerialization JSONObjectWithData:responseData options:NSJSONReadingMutableContainers error:&parseError];
            
            if (httpResponse.statusCode == 201) {
                NSLog(@"Session established. Response body: %@", result);
                NSDictionary *responseHeaders = [httpResponse allHeaderFields];
                
                // These are important pieces of connection information that all ICWS
                // calls which require a session will need.
                self.resourceHelper.csrfToken = responseHeaders[kININHeaderCsrfToken];
                self.resourceHelper.sessionId = responseHeaders[kININHeaderSessionId];
                
                NSDictionary *messagingFeature = nil;
                for (NSDictionary *feature in result[@"features"]) {
                    NSString *featureId = feature[@"featureId"];
                    NSNumber *version = feature[@"version"];
                    
                    if ([featureId isEqualToString:@"messaging"] && version.intValue >= 2) {
                        messagingFeature = feature;
                        break;
                    }
                }
                
                NSNumber *messagingVersion = messagingFeature[@"version"];
                if (messagingVersion.intValue >= 2) {
                    [self startReceivingServerSentEvents];
                }
                else {
                    [self showExamplePoll];
                }
            }
            else {
                NSLog(@"Could not create session.  Received status code %ld and body: %@", (long)httpResponse.statusCode, result);
            }
        }];
        
        
    }

    - (void)showExamplePoll
    {
        // Poll the server of any events that have occurred.  This should be expected
        // on a regular interval.
        ICWSResourcesMessagingMessages *messagesResource = [[ICWSResourcesMessagingMessages alloc] initWithDelegate:self.resourceHelper];
        ICWSRequestsMessagingMessagesGetMessages *messagesRequest = [[ICWSRequestsMessagingMessagesGetMessages alloc] init];
        
        [messagesResource getMessages:messagesRequest withCompletionBlock:^(NSHTTPURLResponse *httpResponse, NSData *responseData, NSError *error) {
            if (httpResponse.statusCode == 200) {
                
                // The messages response contains an array of server side
                // events that were retrieved.
                NSArray *messages = [NSJSONSerialization JSONObjectWithData:responseData options:kNilOptions error:nil];
                for (NSDictionary *messageDictionary in messages) {
                    
                    id message = [ININMessagingMessage representationFromDictionary:messageDictionary];
                    if (message == nil) {
                        NSLog(@"Unrecognized message!  %@", messageDictionary);
                        continue;
                    }
                    
                    NSString *messageType = [messageDictionary objectForKey:@"__type"];
                    NSLog(@"Received '%@' message.", messageType);
                    
                    // Do something with the message, like post it to
                    // NSNotificationCenter for observers to consume.
                }
                
                NSLog(@"Received successful response to /messages.");
            }
            else {
                NSLog(@"Could not retrieve messages.  Received status code %ld.", (long)httpResponse.statusCode);
            }
        }];
    }

    - (void)startReceivingServerSentEvents
    {
        NSLog(@"The server is capable of server-sent events!");
        
        // Begin receiving server-sent events here.
    }

    @end