Creating a Share Extension in NativeScript
Tags: nativescript, javascript, ios
Published: 2019-10-03 13:56:09

Share extensions are a type of app extension in iOS that extend functionality to your app. Users will be able to share other forms of content with your app. Think sharing an article you enjoy in Safari over WhatsApp, your photos over Instagram. Nativescript as of version  5.3 has also introduced beta support for share extensions. I have worked with NativeScript to launch a share extension enabled app into production and found the overall process pleasant.

## A primer to share extensions
Before diving into creating a share extension, let's understand how share extensions work. Share extensions are bundled together with your main app but have their own life cycle and environment. Unlike your host app, the share extension is not run until the user chooses it from the iOS share sheet. One other thing to note is that the share extension does not communicate or share data directly with the host app. In iOS, related apps and extensions share data via App Groups.

## Creating a share extension in NativeScript
Creating a share extension in NativeScript is largely similar to how you would do it natively via Xcode. If you already have experience with doing it natively, feel free to skip straight to the NativeScript-specific part. Otherwise, the process looks like this:

* Using Xcode to scaffold a share extension
* Integrating it into NativeScript's build process
* Coding your share extension
* Sharing data with your host app

### Scaffolding a share extension with Xcode
First, we will want to use Xcode to generate a scaffold of our share extension. This will give us a basic working share extension. Open your NativeScript app's iOS Xcode project located in `platforms/ios`. NativeScript uses CocoaPods, so make sure you open the `.xcworkspace` file instead of your `.xcodeproj` file.

There are already countless guides out in the wild documenting how to do this in Xcode, so I will link you to the [official Apple one](https://developer.apple.com/library/archive/documentation/General/Conceptual/ExtensibilityPG/ExtensionCreation.html) instead of repeating it here. Feel free to go with either Swift or Objective-C as both will work with NativeScript.

After this, you will need to setup an App Group to share data between your extension and host app. In Xcode, go to your project's capabilities tab to create a new App Group. In your list of project targets, go to your main host app and enable the App Group for it as well.

### Integrating your share extension into your NativeScript app

You have a working share extension in your Xcode project already, but it is not yet integrated into NativeScript. However, as this is created inside Xcode, NativeScript will override them the next time you run `tns prepare`.

In Xcode, you will see a newly generated folder for your share extension. Replicate the contents inside to `app/App_Resources/iOS/extensions/your_share_extension_folder`. Now when you run `tns prepare`, it is copied into your Xcode project.

When you build and run your app in Simulator now, you should see a new share extension for your app when you open up the share sheet in Safari. Congratulations!

### Retrieving share extension data in your NativeScript app

This guide will not go into the specifics of coding out the share extension as well. Instead, let's explore how we can retrieve data shared from your extension. To recap what we have done previously, we created an App Group, which will let us share data between the extension and host app.

In your extension, you will probably be saving data into the App Group via UserDefaults:
```
self.userDefaults = [[NSUserDefaults alloc] initWithSuiteName:GROUP_IDENTIFIER];
[self.userDefaults setObject:shareJsonString forKey:@"share"];
```

In NativeScript, the Application Settings module is used to interact with iOS's NSUserDefaults. However, Application Settings is limited to only interacting with the app's User Defaults. To do so with our App Group, we will have to use the native APIs.

```js
import { isIOS } from 'tns-core-modules/platform';

const userDefaults = isIOS ? NSUserDefaults.alloc().initWithSuiteName('group.com.yourapp.shareext') : undefined;

# Retrieving the value from a key
userDefaults.valueForKey(key)
```

### Debugging your share extension

When using Nativescript CLI to build and run your app, you will see that the console only outputs logs from your host app. Should you need more in-depth logging or utilise other debugging strategies like breakpoints, you will need to target the share extension in Xcode and run it. Share extension related logs will be output in the Xcode console.

Overall, the process of developing a share extension in NativeScript went quite smoothly for me. Though support by NativeScript is only in beta, it is good enough to be deployed into the wild as a production app. Creating a share extension is a complex topic by itself and even more so doing it in NativeScript. I am sure I have overlooked some details in writing this guide. Please feel free to reach out if there is something else I can clarify more on or if you have any questions / feedback.

This post was first written on my [personal blog](https://www.bryanleetc.com/creating-a-share-extension-in-nativescript/) where you can find more posts related to NativeScript development. Feel free to also reach out to me directly over [LinkedIn](https://www.linkedin.com/in/bryan-tc/) or [Twitter](https://twitter.com/bryanleetc).