Menu Search
Jump to the content X X
Smashing Conf New York

We use ad-blockers as well, you know. We gotta keep those servers running though. Did you know that we publish useful books and run friendly conferences — crafted for pros like yourself? E.g. upcoming SmashingConf Barcelona, dedicated to smart front-end techniques and design patterns.

Putting Mobile Back End As A Service Into Practice (Part 1)

In a previous article1 I introduced mobile back end as a service (MBaaS) which aims at giving app developers the ability to create seamlessly new feature-complete cross-platform native and web applications.

The next step is implementing a complete demo application using those ideas. Through this real working application, you will be able to see the areas in which MBaaS provides value. This first part will walk you through a messaging application demo powered by the Kinvey application and explore how to leverage user management, file storage and the data store.

The second part will complete the demo and demonstrate how to leverage two key pieces of Kinvey functionality: the permissions provided by the data store, and push notifications, which are enabled through the business logic functionality.

Setting Up Link

Before jumping into the demo application, I want to highlight a few points. First, because I am using a real app to discuss MBaaS, knowledge of the development platform would be extremely helpful. I am leveraging iOS with Swift. In addition, knowing how to integrate with back-end services would certainly be helpful, in order to understand more about what Kinvey is doing under the hood. While all of this is helpful, the application’s full source is included; feel free to analyze the code at your own pace.

Secondly, because the demo application has more of an enterprise focus (as opposed to a consumer focus), I chose Kinvey2 for the MBaaS platform. In the last article3 I walked through the process of evaluating MBaaS providers. Note that Kinvey is not a free service, and licensing terms are attached to its SDKs (as one would expect). Licensing terms are included with each SDK download. You can get more information at the following links:

A Demo Application Link

In the past three years, several clients have approached me about developing an internal messaging platform for their organization. This need has led to the success of such companies as Slack6 (which we use internally at Universal Mind7) and others like it. Because this was a common request, I wanted to see what it would take to implement a basic one-to-one messaging solution for an organization over top of an MBaaS solution.

To help you understand these concepts in a real application, I have provided the application’s entire source code. You can check it out on Github, “WaterCooler Demo8.”

Note: For more information on how to choose between the available MBaaS options, please see the initial article in this series, “Understanding Mobile Back End as a Service9.”

Screenshots of WaterCooler app10
WaterCooler demo messaging app. (View large version11)

Summary of Requirements Link

To illustrate how an MBaaS solution can power an app like this one, we need to meet a few key requirements. Users should be able to do the following with the app:

  • create an account and set up their profile (including name, title, profile picture, email address and password);
  • log in (and be required to log in only once — at least until they log out);
  • exchange one-to-one messages with other members (visible only to the sender and recipient and inaccessible to other users);
  • browse a directory of members who currently have an account on the platform;
  • log out;
  • manage and update their profile information;
  • be alerted through a push notification that they’ve received a new message.

The following sections detail how I used Kinvey to meet these requirements. While I won’t go into detail on how every part of the application was created, I will give full context of the areas where Kinvey was leveraged.

Technical Details Link

The demo application is an iOS app targeting iOS 8+. It utilizes Swift (Xcode 6.1.1 and iOS 8.1.3).

The user interface was created following standard UI principles for iOS. It leverages Auto Layout12 (both within the storyboard and programmatically). The creation of this interface is beyond the scope of the article, but hopefully the example code will be helpful for your iOS applications.

Getting Started With Kinvey Link

If you’re following along, you’ll probably want to build the source code and run the application yourself. To do this, you will need both to create a Kinvey app and to include the credentials for the app in your code.

Creating a Kinvey App and Environment Link

To create a Kinvey app and environment, you will need to create a Kinvey account13. After signing up, select “Get Started with Your First App.” From this page, give your app a name, select iOS and the platform, and then click “Create App.”

Screenshot of creating an app in Kinvey14
A view of the process of creating an app in Kinvey. (View large version15)

From here, you will have an app created with a single development environment. Clicking on the “Development” environment will take you to the console. In the console, you will see both your appKey and appSecret in the top right. Copy these pieces of information because you’ll need to include them in the iOS app.

Configuring the iOS Application Link

Once you have created your Kinvey app and gathered your credentials, grab the code from the repository. Next, open the AppDelegate.swift file and update these values in the application:DidFinishLaunchingWithOptions: method.

// Extracted from AppDelegate.swift (http://tuck.cc/1w7wkyI)

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {

 // --------------------------------------------------------------------
 // INCLUDE YOUR KINVEY CREDENTIALS HERE
 // --------------------------------------------------------------------

 let appKey = ""
 let appSecret = ""

 //---------------------------------------------------------------------

 …
}

Once this is in place, you should be able to run the application as expected. If you want to run the application on a device, you will have to update the code signing as provisioning profiles (as with any iOS application).

  • For more information on setting up an iOS application with Kinvey, check out the “Getting Started16” tutorial.

User Management Link

One foundational element of any MBaaS is user management. This application will leverage user management to control individual user accounts and their respective profile information, as well as provide a directory of all users in the system. Just as with the rest of the functionality we will cover, this integration is provided through Kinvey’s iOS SDK17.

Sign-up, log-in and profile views18
A view of the sign-up, log-in and profile views in the application. (View large version19)

Creating a User Link

The first step in the process is to enable a user to create an account. When a user launches the application, they will land on the view that allows them to either log in or sign up. If the user selects “Sign Up,” they will be taken to the “Sign Up” page, which will guide them through the process of entering their profile information. When this process is complete, the code below is executed, which creates an account and logs the user into the application.

In this example, you will see the KCSUser class. This class handles the representation of a user and is also the gateway for all operations related to user management:

// Extracted from SignupViewController.swift (http://tuck.cc/1vsaWcr)

// Set the parameters of the user
var userParams = [
 KCSUserAttributeGivenname : firstNameField.text,
 KCSUserAttributeSurname : lastNameField.text,
 KCSUserAttributeEmail : emailField.text,
 kWaterCoolerUserTitleValue : titleField.text
];

// Save the user to Kinvey
KCSUser.userWithUsername(emailField.text, password: passwordField.text, fieldsAndValues: userParams) { (user:KCSUser!, error:NSError!, result:KCSUserActionResult) in
 if(error != nil) {
 println("USER NOT CREATED - ERROR: " + error.description)
 } else {
 // User created successfully
 // Do other tasks, such as uploading profile picture to the file store
 }
}

In this case, the fields for first name, last name and email address are include in the KCSUser object. However, Kinvey allows us to save other pieces of data in this object as well. The user’s title will be saved in one of these additional fields. An extension to the KCSUser object is also included (as seen below) to make it easier to access this value for a user within the application:

// Extracted from KinveyExtensions.swift (http://tuck.cc/1vsb5N7)

// Create a constant for accessing the title key from the user object
let kWaterCoolerUserTitleValue = "title"

extension KCSUser {
 var title:String {
 return self.getValueForAttribute(kWaterCoolerUserTitleValue) as String!
 }
}

Logging In Link

If the user selects the option to log in from the landing page, they will be able to enter their email address and password (which they entered in the sign-up process). They are presented with an alert if their attempt is unsuccessful, and if they log in correctly, they are redirected to the main view of the application.

// Extracted from LandingPageViewController.swift (http://tuck.cc/1vsbeAe)

func attemptLogin() {
 // Get the values from the form
 let username = loginEmailField.text
 let password = loginPasswordField.text

 // Attempt to log in to the application
 KCSUser.loginWithUsername(username, password: password) { (user, error, actionResult) -> Void in
 if(error == nil) {
 self.successfulLogin()
 } else {
 self.incorrectLoginWithError(error)
 }
 }
}

func incorrectLoginWithError(error:NSError) {
 // Let the user know an error occurred in login. In this case
 // we just present an alert using the UIAlertController.
 let alert = UIAlertController(title: "Failed Login", message: error.localizedDescription, preferredStyle: UIAlertControllerStyle.Alert)
 alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.Cancel, handler: { (alertAction) -> Void in
 self.dismissViewControllerAnimated(true, completion:nil)
 }))

 // Present the alert
 presentViewController(alert, animated: true, completion: nil)
}

func successfulLogin() {
 // There is already a segue defined to the main threads view.
 // We need to perform this segue if we have a successful login.
 performSegueWithIdentifier(WaterCoolerConstants.Segue.Login, sender: self)
}

Logging Out Link

From the profile management page, the user can log out of the application. Upon doing this, Kinvey’s iOS SDK also does some additional work in the background, including clearing out any cached values. In this example, after logging out, the user is redirected back to the landing page.

// Perform the log-out and send the user to landing page
@IBAction func logout() {
 KCSUser.activeUser().logout()
 performSegueWithIdentifier(WaterCoolerConstants.Segue.Logout, sender: self)
}

User Directory Link

To fulfill all of our requirements, the application also needs to provide a list of all users. A special collection, KCSCollection.userCollection(), provides access to the collection of users for an application. Once you have created a store from this collection, you can query it as you would any other data collection. The following example illustrates how to fetch all users for the application:

// Extracted from KinveyDataManager.swift (http://tuck.cc/1vsd0Bp)

// Create the app data store corresponding to the users collection
lazy var userStore:KCSAppdataStore = {
 let userCollection:KCSCollection = KCSCollection.userCollection()
 let store = KCSAppdataStore(collection: userCollection, options: nil)
 return store
}()

// Fetch the users from the user store
func fetchUsers(completion: ([KCSUser]!, NSError!) -> ()) {
 userStore.queryWithQuery(KCSQuery(), withCompletionBlock: { (results, error) -> Void in
 if(error == nil) {
 self.users = results as [KCSUser]
 completion(results as [KCSUser]!, nil)
 } else {
 completion(nil, error)
 }
 }, withProgressBlock: nil)
}

Note: For more information on managing users with Kinvey’s iOS SDK, be sure to check out the “Users20” guide.

File Management Link

One powerful feature of many MBaaS solutions is file storage. In our WaterCooler application, this comes into play when a user creates an account and adds a profile picture. We could also leverage this heavily to extend the app to support the uploading of images within messages. In this process, the file is uploaded to a content delivery network (CDN) and, like any other piece of data, has a full configuration of permissions.

// Extracted from SignupViewController.swift (http://tuck.cc/1vsaWcr)

// Upload the profile picture to the Kinvey file store
func uploadProfilePicture(completion:(file:KCSFile!) -> ()) {
 if((self.photo.image) != nil) {
 let photoData = UIImageJPEGRepresentation(self.photo.image, 1.0)

 KCSFileStore.uploadData(photoData, options: fileParams, completionBlock: { (file:KCSFile!, error:NSError!) -> Void in
 completion(file: file);
 }, progressBlock: nil);

 } else {
 completion(file: nil);
 }
}

// Once we have completed the file upload, assign the file ID to the user
// using a custom attribute
func assignProfilePictureIdToUser(user:KCSUser, picture:KCSFile, completion: () -> Void) {
 user.setValue(picture.kinveyObjectId(), forAttribute: kWaterCoolerUserProfilePicFileId);
 user.saveWithCompletionBlock { (user:[AnyObject]!, error:NSError!) -> Void in
 completion();
 }
}

In the code above, two distinct steps are occurring. First, we are uploading the profile picture to the file store. Once this process is completed, we are updating the user with the ID that the file store has returned. In this manner, we are leveraging yet another custom property on the user to store an identifying piece of information. Now, anywhere we display a list of users, we can also display their profile picture.

Note: For more information on working with files in Kinvey’s iOS SDK, see the “Files21” guide.

Data Model Link

One of the benefits of Kinvey’s iOS SDK is that it allows you to map your Swift (or Objective-C) objects to Kinvey collection objects. The KCSUser class is a special class that is already defined and mapped to the user object, but in our case we will create two additional data classes that map to conversations and the messages within them.

WaterCooler Data Model Link

The WaterCooler data model will have two main entities, Message and MessageThread.

The MessageThread class will be responsible for representing a conversation between two users. It will contain information about the users involved in the conversation, as well as a reference to the last message sent in the conversation.

Within Kinvey, the entityId is a special field. If you do not assign a value to it, the system will assign one when the object is saved to the data store. In our case, we will go ahead and define a special value that maps to the two users who are in a conversation for the MessageThread class. The method that calculates this value can be seen below:

// Extracted from MessageThread.swift (http://tuck.cc/1w7jdOd)

// This method simply takes a user and the current user and creates
// an ID based on the alphabetized array of user IDs between these
// two users. In this way, we don't have to fetch additional information
// when displaying the message thread view.
class func threadIdentifierForUser(user:KCSUser) -> String {
 let userAIdentifier:String = KCSUser.activeUser().userId
 let userBIdentifier:String = user.userId
 let identifiers:[String] = [ userAIdentifier, userBIdentifier ]
 let sortedIdentifiers = identifiers.sorted {
 $0.localizedCaseInsensitiveCompare($1) == NSComparisonResult.OrderedAscending
 }
 return ":".join(sortedIdentifiers)
}

The Message class will be responsible for tracking an individual message within an overall conversation. This class contains information about the message, including its time, contents, sender and related message thread. To get all of the messages for a particular conversation, we simply query based on the threadId of the conversation. The following code fetches all of the messages for a predefined message thread:

// Extracted from KinveyDataManager.swift (http://tuck.cc/1vsd0Bp)

func messagesForThread(thread:MessageThread, completion:([Message]) -> ()) {
 let query = KCSQuery(onField: "threadId", withExactMatchForValue: thread.entityId)
 messagesStore.queryWithQuery(query, withCompletionBlock: { (results, error) -> Void in
 completion(results as [Message])
 }, withProgressBlock: nil)
}

Data Model Relationships Link

Kinvey supports data model relationships within both the core data store as well as the iOS SDK. In our situation, the lastMessage property on the MessageThread class is one such instance. When we fetch a thread, it looks at specific methods in our class to determine how it should handle references to other collection objects. In our case, the following methods allow it to treat this reference as a Message instance:

// Extracted from MessageThread.swift (http://tuck.cc/1w7jdOd)

// This method tells Kinvey to save the message in the lastMessage property
// when the thread is saved. If this method were not included, the message
// itself would not be saved when the thread is saved.
override func referenceKinveyPropertiesOfObjectsToSave() -> [AnyObject]! {
 return [
 "lastMessage"
 ]
}

// This maps the properties in the class to specific values in the Kinvey
// data store.
override func hostToKinveyPropertyMapping() -> [NSObject : AnyObject]! {
 return [
 "entityId" : KCSEntityKeyId,
 "lastMessage" : "lastMessage",
 "metadata" : KCSEntityKeyMetadata
 ]
}

// This method tells Kinvey that the lastMessage property is a member of
// the Messages collection. (You need to put the name of the Kinvey collection
// here and not the name of the class.)
override class func kinveyPropertyToCollectionMapping() -> [NSObject : AnyObject]! {
 return [
 "lastMessage" : "Messages"
 ]
}

// Here you tell Kinvey which class to map the lastMessage property to. This
// is how it knows how to build the object when it fetches it from the server.
override class func kinveyObjectBuilderOptions() -> [NSObject : AnyObject]! {
 let referenceMap:[NSObject : AnyObject] = [
 "lastMessage" : Message.self
 ]
 return [
 KCS_REFERENCE_MAP_KEY : referenceMap
 ]
}

Data Model Classes in Swift Link

For data model classes to work properly in Swift, they need to be able to leverage the default initializer. This means you need to have a default value for each property within the class. You can still leverage convenience initializers, as we have done here with the Message class:

// Extracted from Message.swift (http://tuck.cc/1w7kkgB)

// This initializer creates a Message instance based on the message text
// and the recipient ID. This is the initializer that is used when a
// user creates a new message in a conversation.
init(messageText:String, recipientId:String) {
 senderId = KCSUser.activeUser().userId
 self.messageText = messageText
 entityId = NSUUID().UUIDString
 metadata = KCSMetadata(userIds: [recipientId], includeActiveUser:true)
}

Note: For more information on the data store and data modeling in Kinvey, see the “Data Store22” guide.

Conclusion Link

Through this process, we have completed the core of Kinvey interactions for the application. However, with all of this in place, two key requirements still have not been met: data permissions and push notifications. In the next article, we will explore the permissions model in Kinvey, as well as the business logic functionality provided by the platform.

(da, al, ml)

Footnotes Link

  1. 1 https://www.smashingmagazine.com/2014/12/15/understanding-mobile-back-end-as-a-service/
  2. 2 http://www.kinvey.com/
  3. 3 https://www.smashingmagazine.com/2014/12/15/understanding-mobile-back-end-as-a-service/
  4. 4 http://www.kinvey.com/pricing-starter
  5. 5 http://www.kinvey.com/pricing
  6. 6 https://slack.com/
  7. 7 http://www.universalmind.com/
  8. 8 https://github.com/davidtucker/WaterCooler-Demo
  9. 9 https://www.smashingmagazine.com/2014/12/15/understanding-mobile-back-end-as-a-service/
  10. 10 https://www.smashingmagazine.com/wp-content/uploads/2015/03/01-watercooler-demo-app-opt.jpg
  11. 11 https://www.smashingmagazine.com/wp-content/uploads/2015/03/01-watercooler-demo-app-opt.jpg
  12. 12 https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/AutolayoutPG/Introduction/Introduction.html
  13. 13 http://www.kinvey.com/
  14. 14 https://www.smashingmagazine.com/wp-content/uploads/2015/03/02-new-app-kinvey-opt.jpg
  15. 15 https://www.smashingmagazine.com/wp-content/uploads/2015/03/02-new-app-kinvey-opt.jpg
  16. 16 http://devcenter.kinvey.com/ios/guides/getting-started
  17. 17 http://devcenter.kinvey.com/ios/guides/getting-started
  18. 18 https://www.smashingmagazine.com/wp-content/uploads/2015/03/03-user-management-opt.jpg
  19. 19 https://www.smashingmagazine.com/wp-content/uploads/2015/03/03-user-management-opt.jpg
  20. 20 http://devcenter.kinvey.com/ios/guides/users
  21. 21 http://devcenter.kinvey.com/ios/guides/files
  22. 22 http://devcenter.kinvey.com/ios/guides/datastore
SmashingConf New York

Hold on, Tiger! Thank you for reading the article. Did you know that we also publish printed books and run friendly conferences – crafted for pros like you? Like SmashingConf Barcelona, on October 25–26, with smart design patterns and front-end techniques.

↑ Back to top Tweet itShare on Facebook

David Tucker serves as the Vice President of Technology at Universal Mind. He is a software architect with more than 14 years of experience in web and mobile development, working closely with Universal Mind's clients to develop an effective technical strategies in the enterprise. David is an author and speaks regularly at industry events.

  1. 1

    24k/year is kinvey’s entry price? You’ve got to be kidding right?

    0
  2. 2

    That is incorrect. Kinvey has two tiers: business (geared at enterprise level solutions) and then indie / startup (geared at single developers and small organizations). The startup / indie pricing has a free tier (as well as one with more features that is $200 per month).

    4
    • 3

      You are correct. It is hidden on a small link at bottom of the pricing page.
      Brilliant marketing stunt: 50% of developers close the page never to visit again.

      6
  3. 4

    What did you use to find the Swift code needed for this? Do they have a Swift documentation, I cant find any.

    -1
    • 5

      There isn’t Swift documentation yet, but if you understand the Objective-C implementation it doesn’t take much to implement it via Swift. You can use my code as a starting place.

      2
  4. 6

    Nice tutorial David, well done!
    Kinvey it’s a fairly big MBaaS and they provide a good reliable solution to hit the ground running when you want to avoid server-side infrastructure ops. The pity is that they don’t still address third party services API integrations that today are a fundamental part of any app which gets built.
    A new breed of BaaS is rising and I’d love if you could have a look at Stamplay (https://stamplay.com), you’re feedback would be great!

    Keep up the good work,
    Giuliano

    3
    • 7

      There are obviously a lot of BaaS solutions out there, but most of them are not enterprise focused. The ability to pull in enterprise data and provide authentication connections to outside auth sources are what sets Kinvey apart. In addition, since they added a full Node.js container for their Business Logic (which is a relatively new feature), the third party integrations are fairly simple as well.

      Not to mention – I’m really surprised that Stamplay doesn’t have native mobile SDK’s. I realize that there is a web focus – but consumers today aren’t concerned with that distinction.

      0
  5. 8

    I’m sorry but this was a waist of my time. Firstly the post fucuses on a paid service and secondly bring directed to a service that isn’t clear on pricing, closed the page in 10 seconds..

    I expect better from something posted on smashing mag.

    99% of readers arent going to be building the next Facebook app, you’d hire a consultant..

    -1
    • 9

      Apologies for pushing into this a bit – but are you assuming that the people who read Smashing Magazine don’t build mobile apps? Are you assuming that those consultants don’t read Smashing Magazine too :) ? Established businesses need mobile apps as well. This isn’t just for the ‘next Facebook’ – it is for any application that needs to store data somewhere besides the device (and any application that fits one of a hundred other use cases).

      There is a free tier to Kinvey (which is called out in the article) so that independent developers can create with it as well. I honestly think that if you are interested in mobile applications, understanding how to leverage a solution like this is an important tool in your arsenal whether you are a consultant or not.

      0

↑ Back to top