Cheetah CES Docs Portal

Navigation
Home
GitHub
Email
Corporate Site

IOS SDK
Introduction
Getting Started
At a Glance: Using the Cheetah Loyalty Kits
Using Sample Application
UI Customization
iOS Kit Reference
Swift SDK Reference

At a Glance: Using the Cheetah Loyalty Kits

Each Kit follows the MVC (Model-View-Controller) pattern to make an app. By moving code to these silos it makes it easier for developers to understand what a certain line of code does. At its core, the kits are broken down into different libraries (such as Core Kit, UIKit, Basic Kit, etc). And each libraries are broken down into the following classes:

  • Model - Each Kit has a component that encapsulates all information regarding a particular object, how it behaves, and how it is linked to or accessed from the Cheetah Digital platform
  • Views - Contains the User interface that your user will interact with
  • Controllers - Tie Models and Views together and acts as the decision maker on what your app will do next
  • Navigators - helps the Controllers on deciding what screen to go to next
  • Helpers - Utility classes that can be used to assist in common tasks like parsing responses, string manipulation, error validation, etc.

Sending Requests

API requests are classified by module. Each API module have methods to send requests.

For example, Activity related requests can be found in the ActivitiesAPI type.
To get all activities of the user:

ActivitiesAPI.getActivities(with: nil) { (result) in
   // Handle request result
	switch result {
    case .success(let apiResponse):
        // Show activities list
    case .failure(let error):
        // Show error
    }
}

Handling Responses

All API request completion closures have a Result type as a parameter. Result types as explained here, carry two object types for success and failure where the failure type conforms to the Error protocol.

In the Cheetah Digital Core framework, the success type is an APIResponse.
The APIResponse consists of:

  • request - The URL request sent to the server.
  • data - The data returned by the server.
  • response - The server’s response to the URL request.
  • value - The associated value of the response from the server. This is the model retrieved from the response. The type of this value depends on the request.
  • listInfo - A ListInfo object representing list information of a request returning a list of values. If the request did not return a list of values, this is nil.

The model from a request’s response can be accessed through the value property of the APIResponse object like so:

	case .success(let response):
		let authenticationInfo = response.value

The failure type which is an Error can be retrieved similarly:

	case .failure(let error):
		let authenticationError = error

Authentication

Signing Up

Create a new user by calling AuthenticationAPI.signUp method like so:

let parameters: [String: Any] = [
	"first_name": "Irene",
	"last_name": "Adler",
	"email": "ireneadler@gmail.com",
	"password": "IAmSherlocked",
	"password_confirmation": "IAmSherlocked"
]

AuthenticationAPI.signUp(with: parameters, completion: { result in
	switch result {
	case .success:
		// Handle successful sign up
	case .failure:
		// Handle error
	}
}

Logging In

Most of the Loyalty API requests requires an access token to be accessed. The access token can be created/retrieved by logging in the user. Login the user using the AuthenticationAPI:

  1. First, import the CheetahDigitalCore.

     import CheetahDigitalCore
    
  2. Then login using one of the AuthenticationAPI login methods.

     AuthenticationAPI.logIn(email: email, password: password) { (result) in
         switch result {
         case .success(let response):
             // Login successful
         case .failure(let error):
             // Login failure
         }
     }
    

    The access token is automatically saved and refreshed when needed.

The socialNetwork parameter is an enum with members: apple, facebook, google, twitter, linkedin.

Fetching Data

Fetching Lists

Objects from the Loyalty API can be fetched into lists. These lists can be customized to be fetched by page with a specified number of items per page, object layout, and sorted.

For example, to fetch a list of rewards:

RewardsAPI.getRewards(with: ["page": currentPage + 1,
                             "per_page": 15,
                             "layout": "mobile_list",
                             "sort_by": "publish_date",
                             "sort_dir": "desc"],
                      showFavorites: false,
                      completion: { (result) in
                        // Handle request result
                        switch result {
                        case .success(let apiResponse):
                            let rewards = apiResponse.value
                            // Show rewards list
                        case .failure(let error):
                            // Show error
                        }
})

Fetching Detail

Objects from the Loyalty API can have its details fetched. Each object will have a designated identifier for its specific type which will be used to specify what object detail to fetch. A layout can also be specified for the detail fetched. The layout of the object detail will depend on what is configured in the admin console.

For example, to fetch a specific reward:

RewardsAPI.getReward(id: 2,
                     with: ["layout": "mobile_detail"],
                     completion: { result in
                     	 // Handle request result
                        switch result {
                        case .success(let apiResponse):
                        	let reward = apiResponse.value
                            // Show reward detail
                        case .failure(let error):
                            // Show error
                        }
})

Respondable Objects

Some objects such as Offer, Challenge and Reward can be responded to. Responding to an object initiates an action associated to that object. Successfully responding to an object gives a response info object relating to it.

Responding to a Challenge

Challenge objects can be responded for a user to receive a prize. There are three ways to respond on the challenge depending on the content to respond with. When responding to a challenge, a Challenge.ResponseInfo is returned containing information on the status of challenge response. If responding to the challenge fails, an error is returned.

To respond to a challenge, you can implement:

```swift
let parameters = ["answer[text]": "My answer"]

ChallengesAPI.respondToChallenge(id: challenge.id,
                                 with: parameters,
                                 completion: { result in
				                     	// Handle request result
				                        switch result {
				                        case .success(let apiResponse):
				                            let responseInfo = apiResponse.value
				                            // Handle Challenge Response Info
				                        case .failure(let error):
				                            // Show error
				                        }
})

```

Responding to an Offer

To respond to an offer, provide the id of the offer like in the example below:

let id = 1
OffersAPI.respondToOffer(id: id, completion: { (result) in
	switch result {
   	case .success(let apiResponse):
		// Handle Offer Response Info
   	case .failure(let error):
   		// Show error
    }
})

Redeeming a Reward

Reward objects can be responded for a user to redeem a reward. There are three ways to respond on the reward depending on the content to respond with. When responding to a reward, a Reward.ResponseInfo is returned containing information on the status of the reward response. If redeeming a reward fails, an error is returned.

To respond to a reward:

```swift
RewardsAPI.redeemReward(id: 249,
                            awardId: nil,
                            address: [
                                "street_address": "221B Baker",
                                "city": "London"
                            ],
                            parameter: ["combination_id": "reward_combination_id"],
                            isResponse: true) { [unowned self] (result) in
                                // Handle request result
                                switch result {
                                case .success(let apiResponse):
                                    let responseInfo = apiResponse.value
                                // Handle Reward Response Info
                                case .failure(let error):
                                    // Show error
                                }
    }

```

Creating a List Controller

Here is an example of how you will integrate the API calls above using the Core Kit and display the items in a list using the UI Kit:

  1. Import needed kits.
    import CheetahDigitalCore
    import CheetahDigitalUI
    
  2. Create a class that inherits from List Collection Controller and provide the loyalty object you want to operate on (e.g. Activity)
    class ActivityListController: ListCollectionController<Activity> {
    }
    
  3. Override the loadContent method and send a fetch API call.
    override func loadContent() {
     isFetching = true
        
     if provider.numberOfItems(in: 0) == 0 {
         statefulViewController?.state = .loading(message: nil)
     }
        
     ActivitiesAPI.getActivities(with: ["page": currentPage + 1], completion: { [weak self] (result) in
         guard let self = self else { return }
         switch result {
         case .success(let apiResponse):
             self.totalItems = apiResponse.listInfo?.totalEntries ?? 0
             let activities = apiResponse.value
             DispatchQueue.main.async {
                 self.updateCollection(with: activities)
                 if activities.isEmpty && self.currentPage == 0 {
                     self.statefulViewController?.state = .empty(
                         message: "Activity.List.Empty".localized,
                         reloadHandler: { [weak self] in
                           self?.refreshContent()
                     })
                 } else {
                     self.statefulViewController?.state = .content
                 }
             }
         case .failure(let error):
             DispatchQueue.main.async {
                 self.statefulViewController?.state = .error(
                     error: error,
                    reloadHandler: { [weak self] in
                      self?.refreshContent()
                 })
             }
         }
         self.isFetching = false
     })
    }
    
  4. Provide an extension to your loyalty object and conform to ListItemCellPresentable.
    extension Activity: ListItemCellPresentable {
     public var imageURL: URL? {
         return nil
     }
        
     public var image: UIImage? {
         return nil
     }
        
     public var title: String {
         return label
     }
        
     public var subtitle: String {
         return activityTimeStamp.prettyTimestamp() + "\n" + label
     }
        
     public func configureListCell(_ cell: ListItemCell) {
            
     }
    }
    
  5. Instantiate and use your view controller as needed.
    let listController = ActivityListController()
    let activityListViewController =  CollectionViewController(collectionController: listController)
    

Next: Using Sample Application