Tag Archives: Mobile SDK for iOS

Adding iOS App Extensions to Salesforce Mobile SDK Apps

If you’re an iOS developer who wants to use cool iOS app extensions in your Salesforce Mobile SDK app–this post’s for you.

iOS app extensions provide opportunities for developers to present their app’s functionality outside of their app context. With Mobile SDK, for example, you can use an extension to show a “most recently used” (MRU) list of accounts in the Today view and also when the user applies 3D Touch to your app icon. The realm of possibilities for extension functionality is vast. If you’re not familiar with iOS app extensions, get started at https://developer.apple.com/library/content/documentation/General/Conceptual/ExtensibilityPG/ExtensionScenarios.html (or search for “iOS app extensions” at https://developer.apple.com/library).

This post gives you some pointers for combining iOS app extensions with Mobile SDK 5.0 native apps. The instructions here are generic enough to be used with all types of extensions. To study a functioning example of an iOS app extension working in a Mobile SDK app, see the SmartSyncExplorer sample app at https://github.com/forcedotcom/SalesforceMobileSDK-iOS/tree/master/native/SampleApps/SmartSyncExplorer. The SmartSyncExplorer app demonstrates 3D Touch and Today view extensions. It also showcases the use of SmartStore in the extension’s widgetPerformUpdateWithCompletionHandler: method.

Let’s get going with configuring your Xcode workspace and customizing your app.

Configure Your Workspace

When you create an iOS app extension in Xcode, you add another build target to your app. Extensions require your main app target and the extension app target to join the same app group. You configure this relationship in your app’s Xcode workspace configuration.

The following steps don’t directly provide instructions for creating an extension–how you handle step 1 is between you and iOS. The subsequent steps describe the Xcode workspace changes that Mobile SDK and iOS require.

  1. In your Mobile SDK app, create an extension target as described in the Apple developer documentation.
  2. Select the top-level node of your Mobile SDK project in the Xcode Project Navigator. This step opens your app’s configuration wizard.
  3. Click General, and then specify a unique bundle identifier for the Mobile SDK app target. This screen capture shows where to set this identifier for a Mobile SDK app target.Bundle setting for iOS app extensons
  4. Repeat the bundle identifier step for the extension target. This identifier must also be unique.
  5. Enable App Groups and Keychain Sharing in your Mobile SDK target.
    1. In your app configuration, choose your Mobile SDK app target and click Capabilities.
    2. Under App Groups, select or create an app group. Use a unique label that identifies your app, such as “group.myapp.shared”.
    3. Under Keychain Sharing, select or create a keychain group. Use a unique label that identifies your app, such as “com.myapp.MyApp”. App group and keychain sharing settings for Mobile SDK app using iOS app extensions
  6. Repeat the App Groups and Keychain Sharing steps for your extension target. NOTE : The two values in the Extension target must exactly match the corresponding values in the application target.App group and keychain sharing settings for iOS app extension

Customize Your Code

To support extensions, you change your AppDelegate class to make it aware of the extension, and then you add similar code to your app extension view controller.

By default, the Mobile SDK AppDelegate class contains “bootstrapping” code that initializes the SDK. When you incorporate an iOS app extension, you add a couple of lines that tell the SDK that you’re working in an app group.

AppDelegate Code Changes

The following steps apply to the init method of your main app’s AppDelegate class.

  • In the init method, add calls to appGroupName and appGroupEnabled methods of SFSDKDatasharingHelper before the existing calls to SalesforceSDKManager.
// Insert these two lines, using your app group name
[SFSDKDatasharingHelper sharedInstance].appGroupName = 
    @"<your app group name>"; 
[SFSDKDatasharingHelper sharedInstance].appGroupEnabled = YES;

// Now it's OK to set SalesforceSDKManager properties ...
[SalesforceSDKManager sharedManager].connectedAppId = 
    @"<your consumer key>"
[SalesforceSDKManager sharedManager].connectedAppCallbackUri = 
    @"<your callback URL>";
[SalesforceSDKManager sharedManager].authScopes = 
    @[@"api", @"web", ...];
  • In the postLaunchAction block, use NSUserDefaults to cache a flag that indicates login success.
[SalesforceSDKManager sharedManager].postLaunchAction = 
    ^(SFSDKLaunchAction launchActionList) {
    ...
    /* Write a boolean indicating that user has logged in 
      using the app. You could share data between your app 
      and extension by saving it into your app group 
      using NSUserDefaults */
    [[NSUserDefaults initWithSuiteName:@"<your app group name>"] 
        setBool:@YES forKey:@"userLoggedIn"];
}

App Extension Code Changes

At runtime, your iOS app extension operates as a second app, so you have to “bootstrap” it as well. You apply the same appGroupName and appGroupEnabled changes as you did in the AppDelegate class. You also set the following SalesforceSDKManager properties in your extension view controller just as you do in your AppDelegate class:

[SalesforceSDKManager sharedManager].connectedAppId
[SalesforceSDKManager sharedManager].connectedAppCallbackUri
[SalesforceSDKManager sharedManager].authScopes

However, extensions can’t perform authentication tasks such as user logins. Instead, you check the NSUserDefaults value that you stored in the AppDelegate code to verify that a user has logged in before calling SalesforceSDKManager. The rest of your extension code is up to you.

The following steps walk you through the required customizations.

  • In your iOS app extension’s view controller class, find your extension’s initialization entry point and add the following Mobile SDK bootstrapping code there.
[SFSDKDatasharingHelper sharedInstance].appGroupName = 
    @"<your app group name>";
[SFSDKDatasharingHelper sharedInstance].appGroupEnabled = YES;

/* Before calling SalesforceSDKManager, check whether a user has 
logged in through the main app. As your condition, use the 
userLoggedIn Boolean value that you set in your app's 
postLaunchAction block. Remember that you saved this value in 
your app group using NSUserDefaults. */

if ([[NSUserDefaults initWithSuiteName:@"<your app group name>"] 
    boolForKey:@"userLoggedIn"]]) {
       
    // Now you can set the following SalesforceSDKManager properties 
    // as you did in your AppDelegate init method
    [SalesforceSDKManager sharedManager].connectedAppId = 
        @"<your consumer key>"
    [SalesforceSDKManager sharedManager].connectedAppCallbackUri = 
        @"<your callback URL>";
    [SalesforceSDKManager sharedManager].authScopes = 
        @[@"api", @"web", ...];
    // Call other Mobile SDK APIs
    // ...
}
// Continue with standard extension implementation
...
  • If the bootstrapping succeeds, your app can use the current user’s shared credentials to access Salesforce data directly in the extension. The following example shows typical REST API calls that you might add to an extension.
...
NSDictionary *fields = @{@"FirstName": @"\%",@"LastName": @"\%"};
SFRestRequest* request = [[SFRestAPI sharedInstance]
    requestForQuery:@"SELECT FirstName,LastName FROM Contact 
        ORDER BY CreatedDate DESC LIMIT 5"];
[[SFRestAPI sharedInstance] send:request delegate:self];
...

REMEMBER: It’s the developer’s responsibility to determine the user’s login status. The iOS app extension code must not attempt to invoke the SalesforceSDKManager object before the user successfully logs in.

For testing iOS app extensions, there’s one important restriction: You must use a real device. You can’t test iOS app extensions in an iOS simulator.

Conclusion

At this point, you’ve learned how to configure a Mobile SDK app to use an iOS app extension. Your next step should be to implement your own extension in a Mobile SDK app. The type of extension you implement is up to you. If you repurpose the code in the SmartSyncExplorer sample app, you can quickly get running with 3D press and Today screen extensions. By default, both widgets show a list of MRU contacts.

The iOS app extensions feature offers a plethora of other possibilities. We’d love to see what you come up with!

Resources

The following resources provide general information on using Mobile SDK for iOS.

Salesforce Mobile SDK Development Guide:
https://developer.salesforce.com/docs/atlas.en-us.mobile_sdk.meta/mobile_sdk/ios_intro.htm

Trailhead module:
https://trailhead.salesforce.com/modules/mobile_sdk_native_ios

Advertisements