SDK

Customizations

In this page we'll dive deeper into several aspects of our iOS library that can be customized to match your needs.

Multiple environments

We strongly recommend you to setup multiple apps in Notificare for several reasons, including the difference from debug and production when it comes to APNS servers. Given this scenario, you'll have, at least, two configuration files — one for your DEV app and another for the PROD app in Notificare. You have complete freedom on how you want to configure your build process, but the one requirement we have is to have the NotificareServices.plist file present in the built app. However, we have described in detail how we recommend setting it up in an article, available here.

Setting keys in code

Instead of relying on the NotificareServices.plist configuration file, it is possible to set those in code. To configure Notificare, you must run the following code before any other interactions with the library.

class AppDelegate: UIResponder, UIApplicationDelegate {

    func application(_: UIApplication, didFinishLaunchingWithOptions _: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.

        Notificare.shared.configure(
            servicesInfo: NotificareServicesInfo(
                applicationKey: "",
                applicationSecret: ""
            ),
            options: nil
        )

        // more code ...
    }
}

The configure() method should be called before calling Notificare.shared.launch() to make sure the correct keys are used. After setting the keys programmatically you can safely delete the NotificareServices.plist file.

Additionally, you need to let Notificare know to not configure itself after the application has been launched. To do that, you can set AUTO_CONFIG to NO in your NotificareOptions.plist.

Disable method swizzling

Our library performs method swizzling to automatically handle the relevant APNS methods in your AppDelegate. If you prefer not to use it, you can set SWIZZLING_ENABLED to NO in your NotificareOptions.plist. However, by doing so, you will have to forward said methods to our library. Below is an example describing how to do it.

class AppDelegate: NSObject, UIApplicationDelegate {
    // ...

    func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        Notificare.shared.push().application(application, didRegisterForRemoteNotificationsWithDeviceToken: deviceToken)
    }

    func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
        Notificare.shared.push().application(application, didFailToRegisterForRemoteNotificationsWithError: error)
    }

    func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
        Notificare.shared.push().application(application, didReceiveRemoteNotification: userInfo, fetchCompletionHandler: completionHandler)
    }
}

Disable crash reporting

By default, our library sends crash reports to our servers, which you can access via the Dashboard > Your App > Events > Application Error, in order to facilitate the debugging process for developers. If you would like to opt-out, you can do so by setting CRASH_REPORTING_ENABLED to NO in your NotificareOptions.plist.

<plist version="1.0">
<dict>
	<key>CRASH_REPORTING_ENABLED</key>
	<false/>
</dict>
</plist>

Disable UNUserNotificationCenter delegate

Our library, by default, will assign itself as the delegate for the UNUserNotificationCenter, automatically handling all the implementation for you. If you do want a different behaviour, you can disable it and implement it yourself in your app. This is done by setting the USER_NOTIFICATION_CENTER_DELEGATE_ENABLED property to NO in the NotificareOptions.plist. Once you disable it, you will need to implement the following methods:

extension AppDelegate: UNUserNotificationCenterDelegate {
    func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
        // More code ...

        // Pass the event to Notificare.
        Notificare.shared.push().userNotificationCenter(center, didReceive: response, withCompletionHandler: completionHandler)
    }

    func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
        // More code ...

        // Pass the event to Notificare.
        Notificare.shared.push().userNotificationCenter(center, willPresent: notification, withCompletionHandler: completionHandler)
    }

    func userNotificationCenter(_ center: UNUserNotificationCenter, openSettingsFor notification: UNNotification?) {
        // More code ...

        // Pass the event to Notificare.
        Notificare.shared.push().userNotificationCenter(center, openSettingsFor: notification)
    }
}

NotificareOptions.plist

You can customise several mechanisms, appearances and options through the NotificareOptions.plist. All properties are optional, so you can cherry-pick which, if any, you would like to customise. Below is the source code containing all possible properties.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>DEBUG_LOGGING_ENABLED</key>
    <true/>
    <key>AUTO_CONFIG</key>
    <true/>
    <key>SWIZZLING_ENABLED</key>
    <true/>
    <key>USER_NOTIFICATION_CENTER_DELEGATE_ENABLED</key>
    <true/>
    <key>PRESERVE_EXISTING_NOTIFICATION_CATEGORIES</key>
    <false/>
    <key>CRASH_REPORTING_ENABLED</key>
    <true/>
    <key>HEADING_API_ENABLED</key>
    <true/>
    <key>VISITS_API_ENABLED</key>
    <true/>
    <key>URL_SCHEMES</key>
    <array>
        <string>com.example.app</string>
    </array>
    <key>CLOSE_WINDOW_QUERY_PARAMETER</key>
    <string>notificareCloseWindow</string>
    <key>IMAGE_SHARING_ENABLED</key>
    <true/>
    <key>SAFARI_DISMISS_BUTTON_STYLE</key>
    <integer>0</integer>
    <key>THEMES</key>
    <dict>
        <key>LIGHT</key>
        <dict>
            <key>BACKGROUND_COLOR</key>
            <string>#000000</string>
            <key>ACTION_BUTTON_TEXT_COLOR</key>
            <string>#000000</string>
            <key>TOOLBAR_BACKGROUND_COLOR</key>
            <string>#000000</string>
            <key>ACTIVITY_INDICATOR_COLOR</key>
            <string>#000000</string>
            <key>BUTTON_TEXT_COLOR</key>
            <string>#000000</string>
            <key>TEXT_FIELD_TEXT_COLOR</key>
            <string>#000000</string>
            <key>TEXT_FIELD_BACKGROUND_COLOR</key>
            <string>#000000</string>
            <key>SAFARI_BAR_TINT_COLOR</key>
            <string>#000000</string>
            <key>SAFARI_CONTROLS_TINT_COLOR</key>
            <string>#000000</string>
        </dict>
        <key>DARK</key>
        <dict>
            <key>BACKGROUND_COLOR</key>
            <string>#FFFFFF</string>
            <key>ACTION_BUTTON_TEXT_COLOR</key>
            <string>#FFFFFF</string>
            <key>TOOLBAR_BACKGROUND_COLOR</key>
            <string>#FFFFFF</string>
            <key>ACTIVITY_INDICATOR_COLOR</key>
            <string>#FFFFFF</string>
            <key>BUTTON_TEXT_COLOR</key>
            <string>#FFFFFF</string>
            <key>TEXT_FIELD_TEXT_COLOR</key>
            <string>#FFFFFF</string>
            <key>TEXT_FIELD_BACKGROUND_COLOR</key>
            <string>#FFFFFF</string>
            <key>SAFARI_BAR_TINT_COLOR</key>
            <string>#FFFFFF</string>
            <key>SAFARI_CONTROLS_TINT_COLOR</key>
            <string>#FFFFFF</string>
        </dict>
    </dict>
</dict>
</plist>

You can find the source code here, where all available properties are shown.

Increase the limit for monitored regions

When location updates are enabled and the appropriate permissions have been granted, our library automatically monitors both regions and beacons. By default, we monitor 10 regions and 10 beacons while inside a region. Since some use cases don't need to account for beacon monitor, you can customize an upper limit for region monitoring. Add the following parameter to the NotificareOptions.plist file to set a custom limit.

<plist version="1.0">
<dict>
    <key>MONITORED_REGIONS_LIMIT</key>
    <integer>20</integer>
</dict>
</plist>

When you set the custom limit to match the operative system limit, no beacons will be monitored. Otherwise, the amount of beacons monitored will be the remaining space space between your custom limit and the operative system's limit.

Localizable Texts

Our library ships with support for multiple languages that can be customized and expanded if needed. To do so, you just have to include the translation keys in your Localizable.strings file and provide the desired texts.

You can find all the available translation keys here.

Using a Strings Dictionary for Rich Push Templates

In iOS 11, Apple extended hidden previews texts to all the apps. This will allow you to display a pre-defined text whenever a user chooses to hide the content of a notification preview in the lock screen or notification center. Include a Localizable.stringsdict file in your project, like the one below, in order to handle those texts correctly.

hidden previews strings dictionary

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>MY_RICH_PUSH_TEMPLATE_TITLE</key>
    <dict>
        <key>NSStringLocalizedFormatKey</key>
        <string>%#@question@</string>
        <key>question</key>
        <dict>
            <key>NSStringFormatSpecTypeKey</key>
            <string>NSStringPluralRuleType</string>
            <key>NSStringFormatValueTypeKey</key>
            <string>u</string>
            <key>zero</key>
            <string></string>
            <key>one</key>
            <string>%u message awaits your answer</string>
            <key>two</key>
            <string></string>
            <key>few</key>
            <string></string>
            <key>many</key>
            <string></string>
            <key>other</key>
            <string>%u messages awaits your answer</string>
        </dict>
    </dict>
</dict>
</plist>

If your app supports several languages, repeat the operation for every localization file. This will allow you to customize how your notifications show in the lock screen when Hidden Previews are enabled.