Understand Forceios Native Apps

Learning Objectives

After completing this unit, you'll be able to:

  • Understand the overall flow of a native iOS Salesforce app.
  • Understand the flow of events during app launch.
  • Understand how AppDelegate and SceneDelegate direct the flow of execution.

Overview of Application Flow

Let’s take a closer look at native iOS apps.

On the surface, a Mobile SDK native app is just a typical iOS app. You can picture its architecture in Model-View-Controller (MVC) terms:

  • Model is the Salesforce Platform database schema.
  • Views come from the nib and implementation files in your project.
  • Controller functionality comes in the form of iOS Cocoa Touch classes, Salesforce Mobile SDK controller classes, and custom controller classes in your app.

Like all iOS apps, Mobile SDK native apps start with a boilerplate main module that sets up the main event loop. Xcode generates this file, and most humans never have reason to touch it. Mobile SDK template apps for iOS 13 also define these classes that you can customize.

AppDelegateHandles Mobile SDK initialization.

SceneDelegate

Handles scene life cycle events and user authentication. If authentication succeeds, control passes to your app's root view controller.

InitialViewControllerContainer for the Salesforce login screen. A root view controller Entry point to your app's content

SceneDelegate defers to a shared SDK manager object to coordinate Salesforce passcode and authentication tasks. The following diagram illustrates the startup flow for a native app using the most basic SDK manager, SalesforceManager. This manager enables authentication but doesn't include Mobile SDK's offline features.

Application flow diagram

By default, forceios native apps use MobileSyncSDKManager, a specialized subclass of SalesforceManager, to initialize Mobile SDK. This class enables the full range of Mobile SDK features.

Application Launch Flow

When a customer opens your app, a fairly complex sequence of events occurs. These events include:

  • Applying your app’s configuration
  • Initializing Salesforce Mobile SDK
  • Validating an app passcode (optional)
  • Performing Salesforce login and authentication
  • Launching your app
A healthy dose of “wiggle room”—for instance, the ability to defer Salesforce login until after startup—can make handling these events a tricky proposition. Luckily, Mobile SDK keeps you from getting tangled up by providing the SDK manager object. This object enforces the proper bootstrap sequence so that you don’t have to worry about most startup events.

How you initialize Mobile SDK depends on your development language.

Most of the code that uses the SDK manager exists in a new forceios app. Let’s examine this code.

  1. In Xcode, open the AppDelegate.swift file.
  2. Scroll to the init method.

Here, you can see the MobileSyncSDKManager object initializing Mobile SDK--it calls initializeSDK()

override init() {
    super.init()
    MobileSyncSDKManager.initializeSDK()
}

Internally, this method passes the class name MobileSyncSDKManager to the "super" (or parent) class, SalesforceManager. Behind the curtain, SalesforceManager sets up observers for app launch and life cycle events, such as user authentication, PIN code failures, and foreground state. Except in extreme cases, you’re never directly involved in these events. 

SalesforceManager also takes two other notable actions: 

  • It creates a shared instance of itself that persists for the rest of the app's life cycle.
  • It configures itself so that the app always gets an instance of MobileSyncSDKManager to perform its SDK manager tasks.

As a result, if your app calls SDK manager methods, MobileSyncSDKManager has a chance to customize what they do. 

Do these changes affect your coding? Yes! Your code must always call SDK manager methods on this single shared instance: 

MobileSyncSDKManager.shared

You'll see an example shortly. First, though, let's take a closer look at your new app's AppDelegate class.

AppDelegate Class

After Mobile SDK is initialized, the remainder of AppDelegate implements UIApplicationDelegate protocol methods that you can customize as needed. Each of these methods contains commented instructions that indicate what you can do for the intended use case. For example, you can:

  • Customize a new scene session
    • To specify your own scene session configuration, customize the return value of the application(_:configurationForConnecting:options:) method.
  • Clean up resources when the customer discards a scene session
    • Use the application(_:didDiscardSceneSessions:) method to release custom resources that your app added to the discarded scenes.
  • Register your app for push notifications
    • Follow the commented instructions in the application(_:didFinishLaunchingWithOptions:) method. Mobile SDK push notifications in iOS require an extension to handle decryption. For an example, see the iOSNativeSwiftEncryptedNotificationsTemplate in the SalesforceMobileSDK-Templates GitHub repo.
  • Register the customer’s device for push notifications
    • If you registered for push notifications, the application(_:didRegisterForRemoteNotificationsWithDeviceToken:) callback method passes you a device token. To register this device token with Mobile SDK and the Salesforce push notification manager, follow the commented instructions
  • Break the news if push notification registration fails
    • Sometimes, the app’s attempts to register for push notifications failed. You receive an error message in the application(_:didFailToRegisterForRemoteNotificationsWithError:) method, which you can handle as you wish.
  • Enable an IDP service
    • Planning to use this app as an identity provider services for your other Mobile SDK apps? Begin by following the commented instructions in the application(openURL:options:) method. To fully implement this feature, configure your apps as described in the Mobile SDK Development Guide.

SceneDelegate Class

The SceneDelegateclass is the launching pad for your app. It initiates Salesforce login, and then passes control to your custom content. But it does much more than that, too.

In Swift apps for iOS 13 and later, the SceneDelegate takes center stage as the manager of SwiftUI views. SceneDelegate handles a scene’s life cycle events, such as 

  • Connecting to the app
  • Entering the foreground or the background
  • Becoming active or inactive
  • Resizing

You can customize your SceneDelegate class to add your own handling for these events. In fact, the template app makes it easy for you to do so—it provides comments in major event handlers that tell you how to proceed.

In Mobile SDK terms, the SceneDelegate is where your custom resources take control. The template app uses SceneDelegate to 

  • Post the Salesforce login screen when it’s necessary—before a user has logged in or anytime a user logs out.
  • Reset the view state when the current user logs out.
  • Import configuration files for the SmartStore and Mobile Sync offline features.
  • Set the window’s root view to the first custom view in the app.

Let’s look at the source code to see how the app displays its views.

  1. In Xcode, open the SceneDelegate.swift file.
  2. Near the top of the class, you can see the first function definition.
    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        guard let windowScene = (scene as? UIWindowScene) else { return }
        self.window = UIWindow(frame: windowScene.coordinateSpace.bounds)
        self.window?.windowScene = windowScene
        AuthHelper.registerBlock(forCurrentUserChangeNotifications: {
            self.resetViewState {
                self.setupRootViewController()
            } 
        })
    }
    This method is the first stop for any scene that's being initialized. The first three lines are boilerplate code. They "connect" the scene to the app--in other words, they attach the scene to an app window so that it can be displayed. The final statement in this method configures the Mobile SDK AuthHelper class to handle current user change notifications. The handler itself is the internal block within the AuthHelper.registerBlock(_:) method call. It calls two custom private methods: resetViewState(_:) and setupRootViewController(). The resetViewState(_:) method restores your app to its pristine start-up condition by taking down any existing view state and then restoring the original root view. We'll delve into setupRootViewController() shortly.
  3. Search for "func initializeAppViewState”. In this method implementation, look at the next to last line:
    self.window?.rootViewController = InitialViewController(nibName: nil, bundle: nil)
    This code sets the self.window?.rootViewController property to a newly created InitialViewController object. The InitialViewController class is defined in your app, and it’s rather sparse and boring. This view, which is the first to appear, is merely a container for the Salesforce login and authorization screens. That’s all you need to know about it. This method is called from the sceneWillEnterForeground event handler.
  4. Search for “func setupRootViewController”. It’s implemented as follows:
    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: AccountsListView()
        )
    }

The setupRootViewController() method performs a couple of significant setup steps.

  • It loads configuration files for the SmartStore and Mobile Sync offline features.
  • It sets the window's root view controller to AccountsListView, a custom SwiftUI view showing a list of account names from the user's org..

Your root view controller is the starting place for your app’s content. To make this choice clear to iOS, setupRootViewController() creates a UIHostingController object and initialize its rootView property to an instance of your app's first view. When this happens, control of the app passes to your custom code. You can reuse view and model classes from the template app or replace them with your own solutions. As discussed in the next section, you'll still call Mobile SDK APIs to access Salesforce resources. But from this point, the app's flow, content, and intent are all yours. Be creative! 

Resources

Keep learning for
free!
Sign up for an account to continue.
What’s in it for you?
  • 1 in 4 land a new job
  • 50% receive a promotion or raise
  • 80% learn new technologies that boost their resume
  • 66% say it increases productivity
Source: Trailblazer Community Impact Survey 2019