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. This sample app demonstrates 3D Touch and Today view extensions. It also showcases the use of SmartStore in the extension’s widgetPerformUpdateWithCompletionHandler: method.

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.

In your Mobile SDK app, create an extension target as described in the Apple developer documentation.

Under App Groups, select or create an app group. Use a unique label that identifies your app, such as “group.myapp.shared”.

Under Keychain Sharing, select or create a keychain group. Use a unique label that identifies your app, such as “com.myapp.MyApp”.

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.

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.

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
in to the 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 also 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:

connectedAppId
connectedAppCallbackUri
authScopes

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

[SFSDKDatasharingHelper sharedInstance].appGroupName = @"<your app group name>";
[SFSDKDatasharingHelper sharedInstance].appGroupEnabled = YES;
/* Before calling SalesforceSDKManager, check if user has logged in through the main app.
Use the userLoggedIn Boolean value that you set in your app's postLaunchAction block by saving it
in the 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.

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.