iOS SDK Setup

Instructions for adding the OneSignal SDK to your iOS native app with Swift or Objective-C

Step 1. Requirements

📘

Installation via the OneSignal CLI

The OneSignal CLI is now available in beta with a command to automate most steps of the iOS SDK setup process.

Step 2. Add a Notification Service Extension

The OneSignalNotificationServiceExtension allows your iOS application to receive rich notifications with images, buttons, and badges. It's also required for OneSignal's analytics features.

2.1 In Xcode Select File > New > Target...
2.2 Select Notification Service Extension then press Next.

1472

2.3 Enter the product name as OneSignalNotificationServiceExtension and press Finish.

Do not select Activate on the dialog that is shown after selecting Finish.

1472

2.4 Press Cancel on the Activate scheme prompt.

300

By canceling, you are keeping Xcode debugging your app, instead of the extension you just created.

If you activated by accident, you can switch back to debug your app within Xcode (next to the play button).

2.5 In the project navigator, select the top-level project directory and select the OneSignalNotificationServiceExtension target in the project and targets list.

Ensure the Deployment Target is set to the same value as your Main Application Target. Unless you have a specific reason not to, you should set the Deployment Target to be iOS 10 which is the version of iOS that Apple released Rich Media for push. iOS versions under 10 will not be able to get Rich Media.

2536

This should be the same value as your Main Application Target.

2.6 In the project navigator, click the OneSignalNotificationServiceExtension folder and open the NotificationService.m or NotificationService.swift and replace the whole file's contents with the following code. Ignore any build errors at this point. We will import OneSignal which will resolve any errors.

import UserNotifications

import OneSignal

class NotificationService: UNNotificationServiceExtension {
    
    var contentHandler: ((UNNotificationContent) -> Void)?
    var receivedRequest: UNNotificationRequest!
    var bestAttemptContent: UNMutableNotificationContent?
    
    override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
        self.receivedRequest = request
        self.contentHandler = contentHandler
        self.bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)
        
        if let bestAttemptContent = bestAttemptContent {
            //If your SDK version is < 3.5.0 uncomment and use this code:
            /*
            OneSignal.didReceiveNotificationExtensionRequest(self.receivedRequest, with: self.bestAttemptContent)
            contentHandler(bestAttemptContent)
            */
            
            /* DEBUGGING: Uncomment the 2 lines below to check this extension is excuting
                          Note, this extension only runs when mutable-content is set
                          Setting an attachment or action buttons automatically adds this */
            //OneSignal.setLogLevel(.LL_VERBOSE, visualLevel: .LL_NONE)
            //bestAttemptContent.body = "[Modified] " + bestAttemptContent.body
            
            OneSignal.didReceiveNotificationExtensionRequest(self.receivedRequest, with: bestAttemptContent, withContentHandler: self.contentHandler)
        }
    }
    
    override func 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.
        if let contentHandler = contentHandler, let bestAttemptContent =  bestAttemptContent {
            OneSignal.serviceExtensionTimeWillExpireRequest(self.receivedRequest, with: self.bestAttemptContent)
            contentHandler(bestAttemptContent)
        }
    }  
}
#import <OneSignal/OneSignal.h>

#import "NotificationService.h"

@interface NotificationService ()

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

@end

@implementation NotificationService

- (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent * _Nonnull))contentHandler {
    self.receivedRequest = request;
    self.contentHandler = contentHandler;
    self.bestAttemptContent = [request.content mutableCopy];
    
    //If your SDK version is < 3.5.0 uncomment and use this code:
    /*
    [OneSignal didReceiveNotificationExtensionRequest:self.receivedRequest
                       withMutableNotificationContent:self.bestAttemptContent];
    self.contentHandler(self.bestAttemptContent);
    */
    
    /* DEBUGGING: Uncomment the 2 lines below and comment out the one above to ensure this extension is excuting
                  Note, this extension only runs when mutable-content is set
                  Setting an attachment or action buttons automatically adds this */
    // NSLog(@"Running NotificationServiceExtension");
    // self.bestAttemptContent.body = [@"[Modified] " stringByAppendingString:self.bestAttemptContent.body];
    
  	// Uncomment this line to set the default log level of NSE to VERBOSE so we get all logs from NSE logic
    //[OneSignal setLogLevel:ONE_S_LL_VERBOSE visualLevel:ONE_S_LL_NONE];
    [OneSignal didReceiveNotificationExtensionRequest:self.receivedRequest
                       withMutableNotificationContent:self.bestAttemptContent
                                   withContentHandler:self.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.
    
    [OneSignal serviceExtensionTimeWillExpireRequest:self.receivedRequest withMutableNotificationContent:self.bestAttemptContent];
    
    self.contentHandler(self.bestAttemptContent);
}

@end

Ignore any build errors at this point. We will import OneSignal which will resolve any errors.

Step 3. Import the OneSignal SDK into your Xcode project

Option 1. Swift Package Manager
The OneSignal SDK can be added as a Swift Package (works with Objective-C as well). See Instructions on how to import the SDK directly from Xcode.

Option 2. Carthage
If using Carthage, see Carthage setup guide.

Option 3. CocoaPods

You must use be using a Cocoapods version >= 1.12.1

3.1 Make sure your current Xcode project is closed and in the project root, run sudo gem install cocoapods.

3.2 Run pod init from the terminal in your project directory.

3.3 Open the newly created Podfile with your favorite code editor.

3.4 Add the OneSignal dependency under your project name target as well as
OneSignalNotificationServiceExtension target like below.

target 'your_project_name' do
  # only copy below line
  pod 'OneSignalXCFramework', '>= 3.0.0', '< 4.0'
  # Your other pods here
end

target 'OneSignalNotificationServiceExtension' do
  # Comment the next line if you don't want to use dynamic frameworks
  use_frameworks!
  pod 'OneSignalXCFramework', '>= 3.0.0', '< 4.0'
end

3.5 Run the following commands in your terminal in your project directory.

pod repo update
pod install

3.6 Open the newly created <project-name>.xcworkspace file.

Make sure to always open the workspace from now on. You can also do this automatically by running xed . from the root of your project.

Step 4. Add Required Capabilities

This step will make sure your project is able to receive remote notifications,

Only do this for the main application target.
Do not do this for the Notification Service Extension.

4.1 Select the root project > your main app target and "Signing & Capabilities"

4.2 If you do not see Push Notifications enabled, click "+ Capability" and add "Push Notifications".

2624

4.3 Click "+ Capability" and add "Background Modes". Then check "Remote notifications".

2762

Step 5. Add the OneSignal Initialization Code

Method 1. Storyboard

If using the Storyboard, navigate to your AppDelegate file and add the OneSignal initialization code to didFinishLaunchingWithOptions.

Make sure to import the OneSignal headers:

  • Swift: import OneSignal
  • Objective-C: #import <OneSignal/OneSignal.h>
import UIKit
import OneSignal

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
  
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: 
[UIApplication.LaunchOptionsKey: Any]?) -> Bool {
  // Remove this method to stop OneSignal Debugging
  OneSignal.setLogLevel(.LL_VERBOSE, visualLevel: .LL_NONE)
  
  // OneSignal initialization
  OneSignal.initWithLaunchOptions(launchOptions)
  OneSignal.setAppId("YOUR_ONESIGNAL_APP_ID")
  
  // promptForPushNotifications will show the native iOS notification permission prompt.
  // We recommend removing the following code and instead using an In-App Message to prompt for notification permission (See step 8)
  OneSignal.promptForPushNotifications(userResponse: { accepted in
    print("User accepted notifications: \(accepted)")
  })
  
  // Set your customer userId
  // OneSignal.setExternalUserId("userId")
  
  

   return true
}
  
// Remaining contents of your AppDelegate Class...
}
#import <OneSignal/OneSignal.h>

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  
  // Remove this method to stop OneSignal Debugging  
  [OneSignal setLogLevel:ONE_S_LL_VERBOSE visualLevel:ONE_S_LL_NONE];
  
  // OneSignal initialization
  [OneSignal initWithLaunchOptions:launchOptions];
  [OneSignal setAppId:@"YOUR_ONESIGNAL_APP_ID"];

  // promptForPushNotifications will show the native iOS notification permission prompt.
  // We recommend removing the following code and instead using an In-App Message to prompt for notification permission (See step 8)
  [OneSignal promptForPushNotificationsWithUserResponse:^(BOOL accepted) {
    NSLog(@"User accepted notifications: %d", accepted);
  }];
  
  // Set your customer userId
  // [OneSignal setExternalUserId:@"userId"];
  
  return YES;
}

Replace YOUR_ONESIGNAL_APP_ID with your OneSignal App ID.

Method 2. SwiftUI

If using SwiftUI, update your main 'APP_NAME'App.swift file and use the code below. Make sure to replace 'YOURAPP_NAME' with your app name.

import SwiftUI
import OneSignal

@main
struct YOURAPP_NAME: App {
    @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
    
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}

class AppDelegate: NSObject, UIApplicationDelegate {
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
       // Remove this method to stop OneSignal Debugging
       OneSignal.setLogLevel(.LL_VERBOSE, visualLevel: .LL_NONE)
        
       OneSignal.initWithLaunchOptions(launchOptions)
       OneSignal.setAppId("YOUR_ONESIGNAL_APP_ID")
        
       OneSignal.promptForPushNotifications(userResponse: { accepted in 
         print("User accepted notification: \(accepted)")
       })
      
      // Set your customer userId
      // OneSignal.setExternalUserId("userId")
      
       return true
    }
}

Step 6. Add App Groups

App Groups allow your app to execute code when a notification is received, even if your app is not active. This is required for features including notification Badges, and Confirmed Deliveries.

Please follow the iOS SDK App Groups setup guide to add the OneSignal App Group in your app.

Step 7. Run Your App and Send Yourself a Notification

Run your app on a physical iOS device to make sure it builds correctly. Note that the iOS Simulator does not support receiving remote push notifications.

You should be prompted to subscribe to push notifications. Check your OneSignal Dashboard Audience > All Users to see your Device Record.

Then head over to Messages > New Push to Send your first Push Notification from OneSignal.

📘

Troubleshooting

If running into issues, see our iOS troubleshooting guide.

Try the example project on our Github repository.

If stuck, contact support directly or email [email protected] for help.

For faster assistance, please provide:

  • Your OneSignal App Id
  • Details, logs, and/or screenshots of the issue.
  • Steps to reproduce

Step 8. Set Custom User Properties

Recommended
After initialization, OneSignal will automatically collect common user data by default. Use the following methods to set your own custom userIds, emails, phone numbers, and other user-level properties.

Set External User Id

Required if using integrations.
Recommended for messaging across multiple channels (push, email, sms).

OneSignal creates channel-level device records under a unique Id called the player_id. A single user can have multiple player_id records based on how many devices, email addresses, and phone numbers they use to interact with your app.

If your app has its own login system to track users, call setExternalUserId at any time to link all channels to a single user. For more details, see External User Ids.

let externalUserId = "123456789" // You will supply the external user id to the OneSignal SDK
OneSignal.setExternalUserId(externalUserId)
NSString* externalUserId = @"123456789"; // You will supply the external user id to the OneSignal SDK
[OneSignal setExternalUserId:externalUserId];

Set Email and Phone Number

Recommended if using Email and SMS messaging.
Use the provided SDK methods to capture email and phone number when provided. Follow the channel quickstart guides for setup:

// Pass in email provided by customer
OneSignal.setEmail("[email protected]")

// Pass in phone number provided by customer
OneSignal.setSMSNumber("+11234567890")
// Pass in email provided by customer
[OneSignal setEmail:@"[email protected]"];

// Pass in phone number provided by customer
[OneSignal setSMSNumber:@"+11234567890"];

Data Tags

Optional
All other event and user properties can be set using Data Tags. Setting this data is required for more complex segmentation and message personalization.

OneSignal.sendTag("key", value: "value")
[OneSignal sendTag:@"key" value:@"value"];

Step 9. Implement a Soft-Prompt In-App Message

Optional
Apple's Human Interface Guidelines recommend that apps "Create an alert, modal view, or other interface that describes the types of information they want to send and gives people a clear way to opt in or out."

OneSignal provides an easy option for a "soft-prompt" using In-App Messages to meet this recommendation and have a better user experience. This also permits you to ask for permission again in the future, since the native permission prompt can no longer be shown in your app if the user clicks deny.

See our Prompting for Push Permissions with an In-App Message Guide for details on implementing this.

👍

Setup Complete!

Visit Mobile Push Tutorials for next steps.