Troubleshooting iOS

Common issues on iOS.

👍

Activate logging when troubleshooting

You can activate WonderPush logs by simply calling WonderPush.setLogging(true).

Our logs report pretty much the entire activity of our SDK. They are all prefixed with [WonderPush] so they're easy to filter in and out.

Don't forget to turn them off in your release build.

Supported configurations for push notifications

Device

Distribution mode

Push certificate environment

Simulator

Not supported

Physical device

Xcode

Sandbox / development

Physical device

TestFlight

Production

Physical device

In-house / Enterprise

Production

Physical device

AppStore

Production

Push certificate

Creating or renewing an iOS Push certificate

Follow this comprehensive article from Apple Developer Account Help: Communicate with APNs using a TLS certificate.

Head to the Apple developer website, go to Accounts, then Certificates, Identifiers & Profiles and click the plus button to add a new certificate. Choose the type Apple Push Notification service SSL (Sandbox & Production):

Then select your app ID (be sure not to select the app ID for the notification service extension):

Follow the rest of the wizard to download your certificate, and open it so it shows in Keychain Access.

We now have to properly export it along its private key before uploading them in the WonderPush dashboard.

  1. Launch Keychain Access on the Mac where you created the certificate request.
  2. In the Category section, select My Certificates.
  3. Find the newly created certificate and expand its content by clicking on the triangle icon.
    You’ll see both a certificate and a private key.
  1. Select both the certificate and the key, and choose File > Export Items.
  2. From the File Format pop-up menu, ensure P12 is selected.
  3. Enter a filename in the Save As field, then click Save.
    The certificate and key are saved to the location you specified as a .p12 file.

Go to Settings / Platforms, click the iOS application section title and fill in:

  • your push certificate by clicking the Browse button,
  • the push certificate password if appropriate.

📘

Be sure to check how to use WonderPush in both Sandbox & Production.

📘

Apple may show you the following warning when renewing your push certificate

Don't worry, we are already up-to-date.

On March 29, 2021, token and certificate-based HTTP/2 connections to the Apple Push Notification service must incorporate the new root certificate (AAACertificateServices 5/12/2020) which replaces the old GeoTrust Global CA root certificate. To ensure a seamless transition and to avoid push notification delivery failures, verify that both the old and new root certificates for the HTTP/2 interface are included in the Trust Store of each of your notification servers before March 29.

Note that Apple Push Notification service SSL provider certificates issued to you by Apple do not need be to updated at this time.

Learn more about connecting to APNs.

If you have any questions, contact us.

Notification display issues

Notifications not shown at all

📘

When a notification is received, WonderPush will add log entries. You can tell when a notification is received by searching the string userInfo in WonderPush logs.

If your device is connected to the Internet via an enterprise network, chances are you are behind a Firewall. Apple push notification service, the technology behind iOS push notifications, requires ports 5223, on IPs 17.0.0.0/8 to be open for notifications to be delivered.

If the notification is received but not displayed:

  1. make sure it isn't a silent notification,
  2. make sure its Text field isn't empty,
  3. make sure its payload's aps.alert.body property has a value.

If the notification is not received and the logs are empty:

  1. make sure you have a valid push certificate,
  2. if you are deploying via Xcode, make sure the push certificate is valid for the sandbox environment,
  3. if you are deploying a production build, make sure the push certificate is valid for the production environment,
  4. find your installationId in the logs and make sure it is part of your notification target,
  5. finally, make sure your notification get sent by observing its number of Notifications sent on the notification detail page.

If you are still experiencing issues, please let us know by chatting with us.

Notification has no Image

  1. Verify the URL of the image by opening it in a web browser. The image should be displayed.
  2. Make sure the URL is a direct link to the image, not an HTML page.
  3. Make sure the URL of the image is HTTPS. If the URL is HTTP, make sure it is allowed by App Transport Security.
  4. Make sure there is no redirect by pasting the URL in a web browser and verifying the URL doesn't change when the image is displayed.
  5. Make sure you've correctly added the Notification Service Extension as described in the quickstart guide
  6. Make sure the Notification Service Extension's Deployment target is iOS 10.0.

Video content is not playing

Check every item of the Notification has no image section as if your video was an image. In addition, also check the following:

  1. Make sure your video content is within the iOS size limitations.
  2. Make sure your video format is supported by iOS by opening the URL of your video in Safari on an iOS device.

Firebase conflicts

Notification clicks not shown on dashboard, universal links stop working

If your iOS app ships with Firebase, make sure Firebase's AppDelegate proxy is disabled by setting FirebaseAppDelegateProxyEnabled to NO in your MyApp-Info.plist file, as explained in the Firebase documentation.

Xcode errors

Automatic signing and provisioning profile errors

If you're getting the following error, make sure to set up Automatic Signing for the extension:

Provisioning profile "XXX" has app ID "YYY", which does not match the bundle ID "YYY.WonderPushNotificationServiceExtension".

If you use a framework and CI/CD automated build tools, make sure to check your framework's solution for automatically setting provisioning.

After installing Xcode 10.3 I get "Failed to find or create execution context for description..."

You just installed Xcode 10.3 and you get a build error similar to:

Failed to find or create execution context for description <IBCocoaTouchPlatformToolDescription: 0x7fa8bad9a6f0>

This worked for us:

sudo killall -9 com.apple.CoreSimulator.CoreSimulatorService

See this stackoverflow answer.

When I run my app, I get this warning: Class WP[...] is implemented in both [...]WonderPushExtension.framework[...] and [...]WonderPush.framework[...]. One of the two will be used. Which one is undefined.

This runtime warning is harmless. It is due to a known CocoaPods issue that results in the main app target being linked against all pods, including those of the notification service extension.

You can safely ignore this warning, but if you want to remove the annoying log messages, here are a few options:

  • In Xcode, find the Pods-MyApp.debug.xcconfig and Pods-MyApp.release.xcconfig files inside the Pods project in the Targets Support Files/Pods-MyApp directory (replace MyApp with your app name). Edit both files to remove -framework "WonderPushExtension" from the OTHER_LDFLAGS setting. This will make the warning go away, but this modification will not survive the pod install command.

  • You can also move away from CocoaPods and use another installation method for WonderPush. We support Carthage Integration and Manual iOS Integration.

I get that message: WARNING: method swizzling detected!

Some frameworks, including WonderPush, try to become the application delegate. That's what our setupDelegateForApplication is for. When several frameworks try to become the application delegate, all are not always successful.

Here are the two steps to resolve it:

  1. In your AppDelegate, stop calling WonderPush.setupDelegate(for: application)
  2. Still in your AppDelegate, forward the following methods to WonderPush:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
  // Override point for customization after application launch.
  WonderPush.application(application, didFinishLaunchingWithOptions: launchOptions)
  return true
}

func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any]) {
  WonderPush.application(application, didReceiveRemoteNotification: userInfo)
}

func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
  WonderPush.application(application, didRegisterForRemoteNotificationsWithDeviceToken: deviceToken)
}

func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
  WonderPush.application(application, didFailToRegisterForRemoteNotificationsWithError: error)
}

func application(_ application: UIApplication, didReceive notification: UILocalNotification) {
  WonderPush.application(application, didReceive: notification)
}

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

func applicationDidBecomeActive(_ application: UIApplication) {
  // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
  WonderPush.applicationDidBecomeActive(application)
}

func applicationDidEnterBackground(_ application: UIApplication) {
  // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
  // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
  WonderPush.applicationDidEnterBackground(application)
}

func application(_ application: UIApplication, didRegister notificationSettings: UIUserNotificationSettings) {
  WonderPush.application(application, didRegister: notificationSettings)
}
- (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions {
  [WonderPush application:application didFinishLaunchingWithOptions:launchOptions];
  return YES;
}

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
  [WonderPush application:application didReceiveRemoteNotification:userInfo];
}

- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
  [WonderPush application:application didRegisterForRemoteNotificationsWithDeviceToken:deviceToken];
}

- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
  [WonderPush application:application didFailToRegisterForRemoteNotificationsWithError:error];
}

- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification {
  [WonderPush application:application didReceiveLocalNotification:notification];
}

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
  [WonderPush application:application didReceiveRemoteNotification:userInfo fetchCompletionHandler:completionHandler];
}

- (void)applicationDidBecomeActive:(UIApplication *)application {
  [WonderPush applicationDidBecomeActive:application];
}

- (void)applicationDidEnterBackground:(UIApplication *)application {
  [WonderPush applicationDidEnterBackground:application];
}

- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings {
  [WonderPush application:application didRegisterUserNotificationSettings:notificationSettings];
}

Debugging the notification extension

To debug the notification extension:

  1. Activate logging in the notification extension by adding the following code to the NotificationService class you've created in the quickstart guide:
func loggingEnabled() -> Bool {
  return true
}
- (BOOL) loggingEnabled {
  return YES;
}
  1. Open the logging console in Xcode under Window > "Devices and Simulators". Select your device on the left and open the log up arrow at the bottom.
  2. Send yourself a notification and look for the string didReceiveNotificationRequest in your device logs.

We do not recommend attaching the debugger to the notification extension, as this can cause the extension to stop working entirely. When this happens, you need to reboot your iOS device.

Notifications have [modified] in the title

When adding a Notification Service Extension target using Xcode, the sample code shows how to modify the notification by appending [modified] to the title.
Remove this sample code and replace it like instructed in the integration guide.