# 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>](/integration/implementation-steps/apple-ios/p8-key-or-p12-cert-setup.md) 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="/files/ARtMNtVjRsQjWhBRmLrk" alt=""><figcaption></figcaption></figure>

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

<figure><img src="/files/DZ13ZkGznp1j2Ym7B05L" alt=""><figcaption></figcaption></figure>

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

<figure><img src="/files/iMVNlr2OB0dkmSa6KwJ0" 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="/files/i2LPQ3Xo7LB8lalaloml" 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="/files/rJQM5DdzcgKwQ16rxcZy" 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="/files/yTEMfBdpo3u015gMUuDK" 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="/files/oZfgkrYoCKHUGz8UYuoQ" 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="/files/i1b3kHNcmqq7WSn5xdAj" 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="/files/zdGxGVSS0kCK8sRjpod7" 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="/files/JBp3BzMBvsX6jjySBlK3" 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>](/integration/implementation-steps/apple-ios/sdk-swift-obj-c/sdk-methods.md#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>](/integration/implementation-steps/apple-ios/sdk-swift-obj-c/deep-linking.md)
* [<mark style="color:blue;">Attaching attributes to a subscriber's profile</mark>](/integration/implementation-steps/apple-ios/sdk-swift-obj-c/sdk-methods.md#adding-attributes-to-a-subscribers-profile)
* [<mark style="color:blue;">Sending information about what content a subscriber interacts with</mark>](/integration/implementation-steps/apple-ios/sdk-swift-obj-c/sdk-methods.md#activity-tracking-url-screen-visits)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://documentation.pushly.com/integration/implementation-steps/apple-ios/sdk-swift-obj-c.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
