Exploring the Salesforce Mobile SDK Using Xcode

John Vester - Mar 27 '22 - - Dev Community

Article Image

Last July, I started writing a series focused on how the Salesforce platform can be utilized in a manner without a traditional Salesforce client. Here are links to the other articles in the series:

  • Leveraging Salesforce Using Spring Boot
  • Leveraging Salesforce Using a Client Written In Svelte
  • Leveraging Salesforce Using a Client Written In Vue.js
  • Leveraging Salesforce Using Mobile Applications Written (Once) In React Native
  • Leveraging Salesforce Using a Client Written In Angular

A graphical representation of the series is shown below:

Leveraging Salesforce

The illustration above shows how various client frameworks can access the Salesforce data without actually utilizing clients provided by the Salesforce ecosystem.

In November 2021, I started a new series to demonstrate the Salesforce Mobile SDK, which harnesses the power of the Salesforce platform within standalone mobile apps.

A graphical representation of this new series is shown below:

Salesforce Mobile SDK

Exploring the Salesforce Mobile SDK Using React Native” was the first article in this Mobile SDK series. I then switched gears for the “Exploring the Salesforce Mobile SDK Using Android Studio” article to leverage Android Studio. In this article, I will focus on using Xcode to produce the same application.

Benefits of the Salesforce Mobile SDK

The Salesforce Mobile SDK provides several benefits for software engineers:

  • Allows custom mobile device applications to utilize Salesforce features and functionality
  • Full access to Salesforce functionality (no need to reinvent the wheel)
  • Applications can be distributed using the application store of the native device
  • Processing push notifications from Salesforce
  • The ability to work with Salesforce data in an offline mode

If your application landscape utilizes Salesforce for key aspects of business operability, then consider leveraging the Salesforce Mobile SDK. By doing so, you can integrate data maintained by Salesforce into key component locations, allowing you to make strong business decisions.

Benefits of Using Xcode

If your client base requires support for iOS devices and you wish to use Xcode for app development, then you’ll find value in the forceios CLI for getting started quickly with Salesforce functionality.

Key features for teams employing Xcode include:

  • Allows use of Swift or Objective-C as the base programming language
  • Provides 100% native support for features and functionality on iOS devices
  • Allows experienced iOS developers to quickly leverage Salesforce Mobile SDK functionality
  • Improvements in error handling, because both Swift and Objective-C maintain a strong typing and error handling design
  • Identify and fix build issues easier

It may be obvious but you must have an Apple computer to use Xcode. For this article, I will be using my 16” MacBook Pro from March 2020.

Now that we’re ready to dive in, let’s briefly review our use case.

Finny’s Foods: An Example Use Case

Having a son (Finny) born with special needs introduced a personal desire to gain an understanding and appreciation of the products we use in our daily life. Years before Finny was born, my wife (Nicole) and I lived a healthy lifestyle. However, as Nicole began deep-diving into the ingredients in the foods that made up our daily diet, we received a much-needed wake-up call.

Fast-forward to today, our diet consists of few processed foods, no gluten, low sugar, and very little dairy. As much as possible, our protein originates from grass-fed sources, and we always favor organic options. Don’t get me started on GMO.

For this series, our Finny’s Foods application provides a simple list of meals that are both acceptable to us and favored by Finny. For now, we will include two simple attributes for each meal:

  • Name of the meal
  • Rating (1 to 5, where a rating of 5 is an absolute favorite for Finny)

Over time, I plan to introduce other attributes (such as summary, ingredients, directions, and even a photo), but let’s walk before we run.

Getting Started with Xcode

In addition to installing git and npm on my MacBook Pro, I made sure my Xcode version was up to date. Next, I visited the following URL to make sure everything was set up and configured as expected:

Set Up Your iOS Development Environment

These steps include making sure Xcode, CocoaPods, node.js, npm, and the forceios CLI are all installed.

Next, I executed forceios from a terminal session with the following options:

forceios create
Enter your application type (native_swift or native, leave empty for native_swift): native_swift
Enter your application name: FinnysFoodsIOS
Enter your package name: com.gitlab.johnjvester.finnysfoods.ios
Enter your organization name (Acme, Inc.): JVC
Enter output directory for your app (leave empty for the current directory):

Once completed, I followed the steps provided by the forceios CLI:

******************************************************************************
*
*   Next steps:
*
*   Your application project is ready in FinnysFoodsIOS.
*   To use your new application in XCode, do the following:
*      - open FinnysFoodsIOS/FinnysFoodsIOS.xcworkspace in XCode
*      - build and run
*   Before you ship, make sure to plug your OAuth Client ID and Callback URI,
*   and OAuth Scopes into FinnysFoodsIOS/FinnysFoodsIOS/bootconfig.plist
*
******************************************************************************
Enter fullscreen mode Exit fullscreen mode

Creating the Meal Object in Salesforce

Before I could begin creating a new application in Xcode, I needed to establish the Meal object in Salesforce.

I already had a Developer org that I could use. (You can create a new one here.) So, I simply logged in using my email address and password for that org. Next, I navigated to the Apps | App Manager and the Setup perspective in Salesforce.

I created a new Lightning App called Meal:

New Lightning App

On the remaining setup screens, I selected all the default settings and granted access to all Salesforce User Profiles.

Next, I visited the Objects & Fields | Object Manager menu option in the Salesforce Settings. Once I located the newly-created Meal item, I used the drop-down component to Edit the object.

I switched from the Details submenu to the Fields & Relationships option. I quickly realized I did not need to create a Name property for my Meal object since Salesforce already took care of that for me. I just needed to add the Rating field.

Using the New button, I selected the number field type and populated Step Two as noted below:

Rating field

I used the default values and saved my new field. Now, I can use both the name and rating fields in my iOS application.

Meal Object

Using the Salesforce client, I populated some source data to develop the application in Xcode. Below is a summary of the submitted values:

Sample Data

Based upon the sample data, Finny always prefers ”Pizza” over “Chicken & Rice”.

Adding Meal Functionality in Xcode

With the source object and data configured, I used my Xcode application to open the finnys-foods-ios project for the first time.

By default, the forceios CLI creates a working application that displays Account and Contact information for the Salesforce org tied to the user account when running for the first time. To make things easier, I decided to go ahead and remove the following files from the project:

  • AccountsListModel.swift
  • AccountsListView.swift
  • ContactDetailModel.swift
  • ContactDetailsView.swift
  • ContactsForAccountListView.swift
  • ContactsForAccountModel.swift

Since I plan to cover offline functionality in a future article, I updated the configuration data in the userstore.json to:

{
  "soups": [
  ]
}
Enter fullscreen mode Exit fullscreen mode

The usersyncs.json file was also purged as shown below:

{
  "syncs": [ ]
}
Enter fullscreen mode Exit fullscreen mode

Next, I created a basic list view for the Meal__c object in Salesforce, called MealsListView.swift.

import Foundation
import SwiftUI
import Combine
import SalesforceSDKCore

struct MealsListView: View {
  var body: some View {
    Text("Finny's Foods (iOS)").bold()
   }
}

struct MealsList_Previews: PreviewProvider {
  static var previews: some View {
    MealsListView()
  }
}
Enter fullscreen mode Exit fullscreen mode

To use the meals list view when the application starts, I updated the setupRootViewController() method in the SceneDelegate.swift file as shown below:

func setupRootViewController() {
       // Setup store based on config userstore.json
       MobileSyncSDKManager.shared.setupUserStoreFromDefaultConfig()
       // Setup syncs based on config usersyncs.json
       MobileSyncSDKManager.shared.setupUserSyncsFromDefaultConfig()

       self.window?.rootViewController = UIHostingController(
           rootView: MealsListView()
       )
   }
Enter fullscreen mode Exit fullscreen mode

At this point, we have a functional iOS application that will merely show “Finny’s Foods (iOS)” using bold text.

Using Font Awesome in Xcode

Before I built out the rest of the application, I wanted to see how easy it would be to add Font Awesome icons in a Swift application created in Xcode. As you may recall, this task was super easy with React Native and not-so-easy in Android studio.

I was able to use the steps provided at the following URL to get things working in about 15 minutes. I fully expect those with Xcode experience to complete these steps in a fraction of the time:

Easy Font Awesome in SwiftUI

As a result of these steps, the following supporting files are now part of my project:

  • fa-brands-400.ttf
  • fa-regular-400.ttf
  • fa-solid-900.ttf
  • icons.json

Creating a Meals List Model

The Xcode application needs to understand the Meal__c object which is driving the Finny’s Foods application. I created a MealsListModel.swift file which contained the following information:

import Combine
import SmartStore
import MobileSync

struct Meal: Hashable, Identifiable, Decodable {
    let id: UUID = UUID()
    let Id: String
    let Name: String
    let Rating__c: Int
}

struct MealResponse: Decodable {
    var totalSize: Int
    var done: Bool
    var records: [Meal]
}

class MealsListModel: ObservableObject {

    @Published var meals: [Meal] = []

    private var mealsCancellable: AnyCancellable?

    func fetchMeals(){
        let request = RestClient.shared.request(forQuery: "SELECT Id, Name, Rating__c FROM Meal__c ORDER BY Name ASC", apiVersion: nil)

        mealsCancellable = RestClient.shared.publisher(for: request)
            .receive(on: RunLoop.main)
            .tryMap({ (response) -> Data in
                response.asData()
            })
            .decode(type: MealResponse.self, decoder: JSONDecoder())
            .map({ (record) -> [Meal] in
                record.records
            })
            .catch( { error in
                Just([])
            })
            .assign(to: \.meals, on:self)
    }
}
Enter fullscreen mode Exit fullscreen mode

This file introduces a Meal object that contains the meta-data for each Meal__c object stored in Salesforce. There is also a MealResponse object, which represents the payload provided by Salesforce when asking for Meal__c data.

With those two key structures defined, the fetchMeals()method makes a RESTful API call to Salesforce, then maps any response data to a list of Meal objects. The MealsListView.swift file created earlier then processes this data.

Updating the Meals List View

With the Meals List Model ready, the Meals List View can now be expanded to integrate with Salesforce and present data onto an iOS device. The first thing I had to do was establish a variable for the Meals List Model in the MealsListView.swift file:

struct MealsListView: View {
  @ObservedObject var viewModel = MealsListModel()
Enter fullscreen mode Exit fullscreen mode

Next, I updated the body variable in the MealsListView.swift file as shown below:

var body: some View {
    Text("Finny's Foods (iOS)").bold()
    List(viewModel.meals) { dataItem in
      HStack(spacing: 10) {
        VStack(alignment: .leading, spacing: 3) {
            HStack {
                Text(dataItem.Name)
            }
        }
      }
    }
    .onAppear{ self.viewModel.fetchMeals() }
Enter fullscreen mode Exit fullscreen mode

At this point, the iOS application shows the name of each meal on a new line. The fetchMeals() method call retrieves data from Salesforce, processing each Meal__c item as dataItem.

However, I really wanted to add the star-rating system used in the React Native project. To do this, I updated the inner-most HStack object as shown below:

HStack {
  Text(dataItem.Name)
  Text(" ")

  switch dataItem.Rating__c {
    case 5:
      FAText(iconName: "star", size: 15, style: .solid)
      FAText(iconName: "star", size: 15, style: .solid)
      FAText(iconName: "star", size: 15, style: .solid)
      FAText(iconName: "star", size: 15, style: .solid)
      FAText(iconName: "star", size: 15, style: .solid)
    case 4:
      FAText(iconName: "star", size: 15, style: .solid)
      FAText(iconName: "star", size: 15, style: .solid)
      FAText(iconName: "star", size: 15, style: .solid)
      FAText(iconName: "star", size: 15, style: .solid)
      FAText(iconName: "star", size: 15)
    case 3:
      FAText(iconName: "star", size: 15, style: .solid)
      FAText(iconName: "star", size: 15, style: .solid)
      FAText(iconName: "star", size: 15, style: .solid)
      FAText(iconName: "star", size: 15)
      FAText(iconName: "star", size: 15)
    case 2:
      FAText(iconName: "star", size: 15, style: .solid)
      FAText(iconName: "star", size: 15, style: .solid)
      FAText(iconName: "star", size: 15)
      FAText(iconName: "star", size: 15)
      FAText(iconName: "star", size: 15)
    default:
      FAText(iconName: "star", size: 15, style: .solid)
      FAText(iconName: "star", size: 15)
      FAText(iconName: "star", size: 15)
      FAText(iconName: "star", size: 15)
      FAText(iconName: "star", size: 15)
  }
}
Enter fullscreen mode Exit fullscreen mode

With these changes in place, the iOS application is ready for use.

Finny’s Foods in Action

Using Xcode, I used the Product menu option and selected the Run option.

First-time use will automatically redirect to a Salesforce login screen, where I used the same email address and password to access my Developer org. After signing in, the Finny’s Foods application appeared, including the five-star rating value for each item.

Finnys Foods in Action

In a matter of minutes, we were able to create an iOS application using Xcode and the Salesforce Mobile SDK.

Conclusion

In this article, I introduced a custom mobile application that deploys natively from the Apple store and uses source code written in Swift. Along the way, we gained a basic understanding of how iOS-based applications are structured.

Starting in 2021, I have been trying to live by the following mission statement, which I feel can apply to any IT professional:

“Focus your time on delivering features/functionality which extends the value of your intellectual property. Leverage frameworks, products, and services for everything else.”

  • J. Vester

The Salesforce Mobile SDK certainly adheres to my personal mission statement, which will benefit any feature team that requires Salesforce functionality as part of custom mobile applications running on iOS devices. Software engineers in this realm of development should certainly consider adding the Salesforce Mobile SDK as a project dependency.

If you wish to see the full source code for this article, visit my project on GitLab:

https://gitlab.com/johnjvester/finnys-foods-ios

Have a really great day!

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .