# SDK: Swift / Obj-C

## Prerequisites

Before you can integrate the SDK with your app the following requirements must be met:

* An iOS 11+ device (iPhone, iPad, or iPod Touch) to develop and test on.
  * **Note:** The XCode Simulator does not support remote push notifications. A physical device must be used.
* A Mac OS device with XCode 14+ (Swift 5.7, if using Swift) installed.
* An iOS P12 Push Certificate or P8 Key. If you do not already have these follow [<mark style="color:blue;">our documentation</mark>](https://documentation.pushly.com/integration/implementation-steps/apple-ios/p8-key-or-p12-cert-setup) to generate them.
* SDK Key: Obtained from the Pushly Platform in the `Domain Settings` page under the `Overview` > `Details` > `Domain Information` section.

## Step 1: Import the PushSDK Framework

{% tabs %}
{% tab title="Swift Package Manager" %}
The PushSDK Framework is compatible with both Swift and Objective-C.

* Select the root project and then your primary application target > `General`
* Click `+` > `Add Other` > `Add Package Dependency` under `Frameworks, Libraries, and Embedded Content`
* Search using the Package URL: [<mark style="color:blue;">https://github.com/pushly/push-sdk-ios</mark>](https://github.com/pushly/push-sdk-ios)
* Set the Dependency Rule to: `Range of Versions` and `1.0.0` < `2.0.0`
* Click `Add Package`

<figure><img src="https://810756845-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Lry9Z27iWOZyQEGAgY7%2Fuploads%2Fur8SV1YwZVDqBNRbLvYW%2FScreen%20Shot%202022-12-16%20at%2012.50.27%20PM.png?alt=media&#x26;token=11c0170c-4375-4ce7-9f72-0077fd73e82f" alt=""><figcaption></figcaption></figure>

* Ensure the `Pushly` option is checked and click `Add Package`

<figure><img src="https://810756845-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Lry9Z27iWOZyQEGAgY7%2Fuploads%2FEXYitjbWrTVuLTouDMPQ%2FScreen%20Shot%202022-12-16%20at%2012.50.52%20PM.png?alt=media&#x26;token=f8eb701a-3b7c-47bc-9229-1259f38dd2bf" alt=""><figcaption></figcaption></figure>

* Finally, add the `Pushly` library to the Primary Application Target

<figure><img src="https://810756845-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Lry9Z27iWOZyQEGAgY7%2Fuploads%2FsuHbbXOjXGKNlZobezvD%2FScreen%20Shot%202022-12-16%20at%2012.51.13%20PM.png?alt=media&#x26;token=c593ae8d-c92b-4dd7-9bc3-102bcd18fe10" alt=""><figcaption></figcaption></figure>
{% endtab %}

{% tab title="CocoaPods" %}
The PushSDK Framework is compatible with both Swift and Objective-C.

CocoaPods Link: <https://cocoapods.org/pods/Pushly>

Add the following to your Podfile:

```
target 'MyApp' do
  pod 'Pushly', '~> 1.1'
end
```

Then run a `pod install` inside your terminal, or from CocoaPods.app.
{% endtab %}
{% endtabs %}

## Step 2: Add the Notification Service Extension

The Notification Service Extension is required to enable rich notifications that support images and custom actions.

Within your app's XCode project select `File > New > Target`. Select `Notification Service Extension` inside the iOS templates tab and click `Next`.

<figure><img src="https://810756845-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Lry9Z27iWOZyQEGAgY7%2Fuploads%2FIKOtBgXyBx78VJBxuNs9%2Fimage.png?alt=media&#x26;token=b0055514-7e75-4ce8-a0b3-bbba8f2543c6" alt=""><figcaption></figcaption></figure>

Enter "NotificationServiceExtension" for the `Product Name` and any other configuration details for your app extension and then click `Finish` but **do not click activate** on the subsequent dialog.

<figure><img src="https://810756845-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Lry9Z27iWOZyQEGAgY7%2Fuploads%2F96yVKAthjykdmnXGXlem%2Fimage.png?alt=media&#x26;token=b8ed3424-44e0-4259-b97b-bb1457411164" alt=""><figcaption></figcaption></figure>

Click `Cancel` on the dialoging prompting you to activate the service extension so that you can set the deployment target once the modal is closed.

<img src="https://810756845-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Lry9Z27iWOZyQEGAgY7%2Fuploads%2FcGXECnSyGjGGEUBg5KDM%2Fimage.png?alt=media&#x26;token=bc91b955-baa5-490f-a32b-dd7367657f9f" alt="" data-size="original">

Make sure to set your deployment target to the **same as your primary application target**. Unless you have a specific reason not to, you should set the `Deployment Target` to be iOS 11 which is the lowest supported version of iOS in the PushSDK Framework and in the most recent releases of XCode.

Next, add the `Pushly` library to your Notification Service Extension:

Click `+` under `Frameworks and Libraries` and select the already imported `Pushly` library.

<figure><img src="https://810756845-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Lry9Z27iWOZyQEGAgY7%2Fuploads%2FK7zOKyVoMmLfbFB5SFif%2FScreen%20Shot%202022-12-16%20at%2012.51.32%20PM.png?alt=media&#x26;token=bf917f13-825a-4905-b13d-404d953a7c4a" alt=""><figcaption></figcaption></figure>

Now, open the newly created Notification Service Extension and replace the code with the following:

{% tabs %}
{% tab title="Swift" %}

```swift
import Pushly

class NotificationService: PNNotificationServiceExtension {
}
```

{% endtab %}

{% tab title="Objective-C" %}

```objectivec
// Make sure to keep the header file import
#import "NotificationService.h"

@import Pushly;

@interface NotificationService ()

@property (nonatomic, strong) void (^contentHandler)(UNNotificationContent *contentToDeliver);
@property (nonatomic, strong) UNMutableNotificationContent *bestAttemptContent;

@end

@implementation NotificationService

- (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent * _Nonnull))contentHandler {
    self.contentHandler = contentHandler;
    self.bestAttemptContent = [request.content mutableCopy];
    
    [PNNotificationServiceExtensionHandler didReceiveExtensionRequest:request content:self.bestAttemptContent withContentHandler:contentHandler];
}

- (void)serviceExtensionTimeWillExpire {
    // Called just before the extension will be terminated by the system.
    // Use this as an opportunity to deliver your "best attempt" at modified content, otherwise the original push payload will be used.
    [PNNotificationServiceExtensionHandler didRecieveExtensionTimeWillExpire:self.bestAttemptContent withContentHandler:self.contentHandler];

    self.contentHandler(self.bestAttemptContent);
}

@end
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
You can ignore dependency errors, such as `Module Pushly not found`, at this point as they will be resolved during the next build.
{% endhint %}

## Step 3: Add Capabilities to Primary Application Target

{% hint style="warning" %}
The Push Notifications capability should only be added to the **primary application target**.
{% endhint %}

Select the root project and then your primary application target > `Signing & Capabilities`

<figure><img src="https://810756845-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Lry9Z27iWOZyQEGAgY7%2Fuploads%2FPEKQiayxyjIphpjeqxB1%2Fimage.png?alt=media&#x26;token=84e69c08-d120-4a48-a193-a272b9e4f109" alt=""><figcaption></figcaption></figure>

Click the `+ Capability` and add `Push Notifications`.

Click the `+ Capability` and add `Background Modes`.

After adding the `Background Modes` capability ensure that `Remote Notifications` are enabled.

<figure><img src="https://810756845-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Lry9Z27iWOZyQEGAgY7%2Fuploads%2FMAfJ7lisFKGMxQvjpIaB%2Fimage.png?alt=media&#x26;token=7b5b4afb-0a24-4b0a-8ef6-594f763231ea" alt=""><figcaption></figcaption></figure>

Click the `+ Capability` and add `App Groups`.

Click the `+` symbol located inside the `App Groups` section to add a new named container. To ensure that the PushSDK can properly capture information the container should be named `group.{app-bundle-id}.push`.

<figure><img src="https://810756845-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Lry9Z27iWOZyQEGAgY7%2Fuploads%2FOR42sYi1kH4o1227pQpY%2Fimage.png?alt=media&#x26;token=c504305e-c703-4e7e-afff-834d9de68aac" alt=""><figcaption></figcaption></figure>

Check the box next to the newly created App Group in the primary application target.

{% hint style="info" %}
If Xcode complains about the new app group at this point you may need to refresh the list after it is done provisioning.
{% endhint %}

## Step 4: Add Capabilities to The Notification Service Extension

Select the root project and then the `NotificationServiceExtension > Signing & Capabilities`

Click the `+ Capability` and add `App Groups`.

Finally, check the box next to the newly created App Group in the `NotificationServiceExtension`.

## Step 5: SDK Initialization

First import the `Pushly` library in your AppDelegate

{% tabs %}
{% tab title="Swift" %}

```swift
import Pushly
```

{% endtab %}

{% tab title="Objective-C" %}

```objectivec
@import Pushly;
```

{% endtab %}
{% endtabs %}

Add the following code to the AppDelegate's `didFinishLaunchingWithOptions` method of your application.

Replace the `REPLACE_WITH_SDK_KEY` in the `setConfiguration` method with the SDK Key from the platform settings page.

{% tabs %}
{% tab title="Swift" %}

```swift
PushSDK.logLevel = .info
PushSDK.setConfiguration(appKey: "REPLACE_WITH_SDK_KEY", withLaunchOptions: launchOptions)

PushSDK.PushNotifications.showPermissionPrompt() { granted, settings, error in
    // optional callback
    print("User accepted permissions: \(granted)")
}
```

{% endtab %}

{% tab title="Objective-C" %}

```objectivec
PushSDK.logLevel = PNLogLevelInfo;
[PushSDK setConfigurationAppKey:@"REPLACE_WITH_SDK_KEY" withLaunchOptions:launchOptions];

[PushSDKPushNotifications showPermissionPrompt:^(BOOL granted, UNNotificationSettings * _Nonnull settings, NSError * _Nullable error) {
    NSLog(@"User accepted permissions: %@", granted ? @"YES" : @"NO")
}];
```

{% endtab %}
{% endtabs %}

## Step 6: Test the Implementation

Run your app on a physical iOS device to make sure it builds correctly.

{% hint style="info" %}
**Note:** The XCode Simulator does not support remote push notifications. A physical device must be used.
{% endhint %}

The code you added in the previous step will show the push permission dialog upon app open. This can be customized using [<mark style="color:blue;">SDK methods</mark>](https://documentation.pushly.com/integration/implementation-steps/apple-ios/sdk-methods#manually-triggering-the-permission-dialog) to control when the dialog shows.

After accepting the dialog, log into the platform and navigate to `Notifications > Create Notification` and send your first notification, targeting the **Native: iOS** channel, to your device.

## Next Steps

Once you have confirmed the SDK is working properly you may continue to add additional optional functionality like:

* [<mark style="color:blue;">Handling notification opens / app links / deep linking</mark>](https://documentation.pushly.com/integration/implementation-steps/apple-ios/sdk-swift-obj-c/deep-linking)
* [<mark style="color:blue;">Attaching attributes to a subscriber's profile</mark>](https://documentation.pushly.com/integration/implementation-steps/apple-ios/sdk-methods#adding-attributes-to-a-subscribers-profile)
* [<mark style="color:blue;">Sending information about what content a subscriber interacts with</mark>](https://documentation.pushly.com/integration/implementation-steps/apple-ios/sdk-methods#activity-tracking-url-screen-visits)
