Author Archives: Richard Whitley

About Richard Whitley

I write the Salesforce Mobile SDK documentation. This is my personal blog account. Opinions here are my own and not those of

Announcing Mobile SDK for iOS 5.0.1

Is your Salesforce Mobile SDK app ready for iOS 10.3? We’ve got your back with the upcoming 5.0.1 patch. You’ll need this patch to support iOS 10.3 in Mobile SDK. This patch has no effect in iOS versions earlier than 10.3. Look for an announcement that the patch is posted on Thursday, February 16, in the SalesforceMobileSDK Google+ community.

Upgrading Mobile SDK for iOS

How you upgrade to Mobile SDK 5.0.1 depends on your project type.

Native apps:

Run pod update in the project folder.

Hybrid apps:

  1. Uninstall and then reinstall forceios:
$>sudo npm uninstall -g forceios
$>sudo npm install -g forceios

2. Recreate your app using the forceios create command.

3. Copy your app’s resources to the www/ folder.

4. If you add plug-ins, be sure to uninstall and then reinstall the Mobile SDK plug-in after adding your last plug-in:

$>cordova plugin add <your last plugin>
$>cordova plugin remove com.salesforce
$>cordova plugin add --force

5. Run cordova prepare.

For questions or issues, please post on the SalesforceMobileSDK Google+ community.


Consuming Mobile SDK for Android Through Gradle

Late-Breaking Feature Addition! Beginning with Salesforce Mobile SDK 5.0, we’re providing native Android libraries on Bintray’s jCenter Maven repository. As a result, you can now consume any Mobile SDK library by adding a single line to the dependencies section of your app’s build.gradle file. 

What’s the value of this change? Upgrade ease! To upgrade a library, you simply change its version number in your build.gradle file to the updated version, and then resync your libraries.

The Details

Here’s how you do it. A typical dependencies section looks like this:

 dependencies {
    classpath ''

To import libraries, you add a Gradle compile statement in this section. A compile statement takes the form

compile 'groupID:artifactID:version'

For Mobile SDK libraries:

  • Group ID is “com.salesforce.mobilesdk”
  • Artifact ID is “SalesforceSDK”, “SmartStore”, or “SmartSync”
  • Version is currently “5.0.0”

The compile statement imports not only the specified library, but also all its dependencies. This means that you never have to explicitly compile SalesforceAnalytics, for example, because every other library depends on it. It also means that you can get everything you need with just one statement.

To import Mobile SDK 5.0.0 libraries, add one of the following lines:

  • For the SalesforceSDK library:
     compile 'com.salesforce.mobilesdk:SalesforceSDK:5.0.0'
  • For the SmartStore library (also imports the SalesforceSDK library):
     compile 'com.salesforce.mobilesdk:SmartStore:5.0.0'
  • For the SmartSync library (also imports the SalesforceSDK and SmartStore libraries):
compile 'com.salesforce.mobilesdk:SmartSync:5.0.0'

Note:  SalesforceHybrid and SalesforceReact libraries are not currently available through Maven.
For more details on the Salesforce Mobile SDK packages on Maven, visit our repository at

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 (or search for “iOS app extensions” at

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 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.


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!


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

Salesforce Mobile SDK Development Guide:

Trailhead module:

iOS: How to Handle Upcoming ATS Restrictions in App Store Submissions

Mobile SDK 5.0 is coming soon–and so are some new restrictions on iOS App Store submissions.


Here’s some background information on the restrictions, plus instructions for making sure your apps comply with the new requirements.

Starting on January 1, 2017, the App Store will reject apps whose info.plist files contain Apple Transport Security (ATS) exceptions.

This article summarizes Apple’s requirements for apps:

App Store Review for ATS

For more background details, see:

ATS Configuration Basics

What It Means for You

Until Nov. 9, 2016, Salesforce servers did not enforce Perfect Forward Secrecy (PFS). As a result, Mobile SDK iOS apps contained exceptions in the info.plist file to get around ATS incompatibilities with Salesforce servers. Nowadays, Salesforce servers are up-to-date with PFS support and are 100% compatible with Apple’s transport security policies.

Beginning Jan. 1, apps that contain these exceptions no longer satisfy App Store security requirements.  If you resubmit an app that contains these exceptions, it will automatically trigger a security review. In order to be accepted, you’re required to make the changes described here.

If you’re developing a new app with Mobile SDK 4.3 or earlier, the Mobile SDK template puts these exceptions in your info.plist file. Be sure to remove them before submitting your app.

How to Fix Your App

Fixing your app is actually simple. You just remove the exceptions from your info.plist file, rebuild, and resubmit to the App Store.

Salesforce Mobile SDK gives you two options for proactively fixing this problem in plenty of time:

  • Now that Salesforce servers comply with Apple’s policies, you can go ahead and remove your exceptions today, well before the deadline, and resubmit to the App Store. Follow the example link below to see what needs to be removed.
  • If you’re too busy to remove the exceptions now, there’ll be an easier way in mid-December: the Mobile SDK 5.0 release. The new release updates our app templates to remove these exceptions. If you simply upgrade your app with forceios 5.0, you’ll get the updated configuration for free–no manual labor required.


To see an example of how we’ve removed the exceptions, check out this pull request:

iOS template for Mobile SDK 5.0:




Errors Creating Hybrid Apps in Mobile SDK 4.3

If you’re upgrading to Mobile SDK 4.3.x and plan to build hybrid apps, heed this tip!

Under certain conditions, the Cordova telemetry feature can cause forcedroid or forceios to fail with bewildering error messages. So far, we’ve seen this problem occur when:

  • You’ve installed the latest version of Cordova (6.2.0 or higher)
  • You’re using forcedroid or forceios to create a hybrid app

If both of the above are true, the script might throw an error such as the following:

“”. Should be in the format x[.y[.ignored]]

) is less than the minimum required version (5.4.0). Please update your version of Cordova.”

These errors occur if you haven’t preset telemetry to some value. Even if you don’t get weird error messages, you’ll still eventually get this prompt asking you to set the telemetry attribute:

May Cordova anonymously report usage statistics to improve the tool over time?

To avoid these hiccups, preset telemetry on or off before you run the script. Just type:

cordova telemetry <on|off>

Afterwards, forcedroid or forceios should work as expected.

For more information, type:

cordova telemetry -h

Creating Hybrid Android Apps with Mobile SDK 4.1.1

If you’re having problems creating hybrid apps with forcedroid–this blog post’s for you.

Lately, our developers have reported errors such as:

“The node package shelljs is required to use this script. Run ‘npm install shelljs@0.5.3‘ before running this script.”


“Error: Execution failed for task ‘:processDebugManifest’.
> Manifest merger failed with multiple errors, see logs”


“Failed to install ‘com.salesforce’:Uh oh! 

/Users/xxxxx/HybridApps/myApp/plugins/com.salesforce/src/android/assets/ not found!”

Errors such as these frequently come from mismatched versions of external dependencies, or unforeseen updates to others. We’re working hard to fix these issues in the upcoming Mobile SDK release. In the meantime, though…Despair not! There’s an easy workaround.

To avoid these issues, we recommend you create and configure your hybrid Android apps entirely from the Cordova command line. You can call cordova create instead of forcedroid create, followed by any other Cordova commands you need. We’ve recommended this approach for a while as an alternative. Nowadays, though, it’s a necessity for these corner cases.

Be careful to observe two important details:

  1. Always add the SalesforceMobileSDK-CordovaPlugin last, after any other plugins.
  2. Specify the version of each platform you add. For Android, use:
cordova platform add android@5.0.0

For iOS:

cordova platform add ios@3.9.2

Note These values apply to Mobile SDK 4.1.1 and will likely change with later releases, so be vigilant!

After you’ve run cordova prepare, open your project in Android Studio and run it from there. Remember to open the project at <project_folder>/platforms/android/.

Here’s an example.

Create a Hybrid Android App with the Cordova Command Line

The following procedure creates a project named “contactsApp” in a target directory named “contactsApps”. This project incorporates the ContactExplorer hybrid sample app from the SalesforceMobileSDK-Shared git repo.

1. cd to a directory you use for storing Mobile SDK hybrid projects.

2.  Run the following commands.

cordova create contactsApp com.salesforce.contactexplorer contactsApp
cd contactsApp
cordova plugin add org.apache.cordova.contacts
cordova plugin add org.apache.cordova.statusbar
cordova plugin add
cp -RL /SalesforceMobileSDK-Shared/samples/contactexplorer/* www/
cordova platform add android@5.0.0
cordova platform add ios@3.9.2
cordova prepare

3. From the Android Studio welcome screen, import the contactsApp/platforms/android folder. If, by any chance, you already have contactsApp installed on your device or emulator, we recommend Force Stopping it and then uninstalling the app before debugging your new app.

4. Run ‘android’.

Mobile SDK 4.0.2 Is Now Available


Following close on the heels of our 4.0 major release and 4.0.1 patch, the 4.0.2 patch for Mobile SDK (Android and iOS) is now available. This patch primarily affects CocoaPods podspecs for iOS developers. We’ve also republished both forceios and forcedroid to keep them on the same version. See the section below for more details on what’s new.

To upgrade:

  1. Uninstall and reinstall forceios and forcedroid from npm.
  2. On iOS, rework your podspecs as described in the following section.
  3. If you use the GitHub repos, merge these tags:

CocoaPods Reorganization

In Mobile SDK for iOS 4.0.1, our podspec configuration didn’t exert enough control over external dependency versions. For 4.0.2, we’ve now removed the SalesforceMobileSDK-iOS podspec and replaced it with a separate podspec for each Mobile SDK module. We’ve also added a new GitHub repo, https://github/forcedotcom/SalesforceMobileSDK-iOS-Specs, that serves as the archive for all versions of our podspecs.

The new podspecs are:

SalesforceSDKCore—Implements OAuth and passcodes. All other pods except FMDB depend on this pod, either directly or indirectly.
SalesforceNetwork—Networking library (with transparent token refresh when session expires). Depends on SalesforceSDKCore.
SalesforceRestAPI—REST API wrappers for accessing Salesforce data. Depends on SalesforceNetwork.
FMDB—The Mobile SDK fork of FMDB, a third-party Objective-C wrapper for SQLite. This fork implements customized logging and
imports SQLCipher with full-text search support.
SmartStore—Implements secure offline storage. Depends on FMDB and SalesforceSDKCore.
SmartSync—Implements offline synchronization. Depends on SalesforceRestAPI and SmartStore.
SalesforceReact—Implements Salesforce Mobile SDK React Native bridges for apps written with React JavaScript and markup. Depends on SmartSync.

Here’s how to update your Podfile for the 4.0.2 patch.

1. In your project’s Podfile, add the SalesforceMobileSDK-iOS-Specs repo as a source before adding the CocoaPods source.

target 'YourAppName' do
# must get SalesforceMobileSDK-iOS-Specs 
# source first (before CocoaPods)! 
source '' 
source ''

2. Declare each pod on a separate line.

pod 'SalesforceSDKCore'
pod 'SalesforceNetwork'
pod 'SalesforceRestAPI'

Or, thanks to dependency chains, this will work if you’re using the current release:

pod 'SalesforceRestAPI'

If you currently have a podspec that calls pod SalesforceMobileSDK-iOS with subspecs for Mobile SDK modules, such as:

pod 'SalesforceMobileSDK-iOS', :subspecs =>[ 'SalesforceRestAPI' ]

Replace this call with individual pod calls, as shown above.

Working with an Unstable Branch

To work with an upcoming release of Mobile SDK, you clone the unstable branch of the SalesforceMobileSDK-iOS repo, and then pull resources from it.

  1. Clone locally at the desired commit.
  2. At the terminal window, run ./ in the root directory of your clone.
  3. To each pod call in your Podfile, add a :path parameter that points to your clone. Note that you shouldn’t skip dependencies if you’re specifying a path—you need to call the pod command individually for each module.

Here’s the previous example repurposed to pull resources from a local clone:

target 'YourAppName' do
# must get SalesforceMobileSDK-iOS-Specs 
# source first (before CocoaPods)! 
source '' 
source '' 

pod 'SalesforceSDKCore', :path => 
pod 'SalesforceNetwork', :path => 
pod 'SalesforceRestAPI', :path => 


For more information, see the Salesforce Mobile SDK Development Guide at