App submission errors can occur when you're publishing your apps to App Store Connect. These errors are accompanied by an error message from Xcode or during Apple's app review.
We identified one or more issues with a recent delivery for your app, “[app name]”. Your delivery was successful, but you may wish to correct the following issues in your next delivery:
Missing Purpose String in Info.plist File - Your app’s code references one or more APIs that access sensitive user data. The app’s Info.plist file should contain a `NSLocationAlwaysUsageDescription` key with a user-facing purpose string explaining clearly and completely why your app needs the data. Starting Spring 2019, all apps submitted to the App Store that access user data will be required to include a purpose string. If you’re using external libraries or SDKs, they may reference APIs that require a purpose string. While your app might not use these APIs, a purpose string is still required. You can contact the developer of the library or SDK and request they release a version of their code that doesn’t contain the APIs. Learn more (https://developer.apple.com/documentation/uikit/core_app/protecting_the_user_s_privacy).
This error can occur even if you aren't using MobilePush Location Messaging. If you're not using the SDK's location messaging functionality, your users aren't prompted to provide location permissions. This error occurs as the SDK is built with references to CoreLocation.framework. During app review, the automated binary scanning detects these references and requires purpose strings to be attached.
If you're not using Location Messaging, add a purpose string to your app’s Info.plist file as a placeholder, as shown in the following example.
Apple Push Notification Service Server Configuration
To ensure the proper configuration of your Apple Push Notification Service (APNS) server and delivery of push notifications for different types of app builds (development or production), keep the following points in mind.
APNS Server Selection
Irrespective of the chosen .p8 key or .p12 certificate, Engagement attempts to contact the Sandbox APNS server when you check the Development radio button, and the Production APNS server when you check the Production radio button.
For Development Apps (Apps Built Using Development Certificates)
To send notifications only to those devices with apps on Debug configuration, choose the Development radio button in the MobilePush Administration page.
For Production Apps (Apps Built Using Production or Distribution Certificates)
To send notifications only to those devices with apps on Release configuration, select the Production radio button in the MobilePush Administration page.
Push Messages Not Displayed
If you encounter issues receiving messages in your app, consider these troubleshooting steps:
The MarketingCloudSDK.framework uses extensive internal logging to record actions performed by the SDK for informational and diagnostic purposes.
General, default-level logging is always enabled. Additionally, the SDK writes error and fault-level logs when conditions occur that must be recorded.
Enable logging using the following call:
8.x
// Turn on logging by selecting the logLevel (debug, warn or error). Debugging is not recommended for production apps.SFMCSdk.setLogger(logLevel:.debug)
When using SDK versions older than version 8.x, enable logging after SDK configuration.
7.x
// turn on logging for debugging. Not recommended for production apps.// Set to true to enable logging while debuggingMarketingCloudSDK.sharedInstance().sfmc_setDebugLoggingEnabled(true)
Enable logging with CustomLogOutputter:
8.x
classCustomLogOutputter:LogOutputter{overridefuncout(level:LogLevel, subsystem:String, category:LoggerCategory, message:String){// custom log outputting code}}// Then set the log level and custom log outputterSFMCSdk.setLogger(logLevel:.debug, logOutputter:CustomLogOutputter())
Enable logging with a standard log output and a log filter. For more filtering options, refer to Xcode autocompletion.
Query the state of debug-level logging using this call.
7.x
let enabled =MarketingCloudSDK.sharedInstance().sfmc_getDebugLoggingEnabled()
The SDK sends all logging output to Apple’s unified logging system. You can review this information using Xcode’s Devices and Simulators window or the macOS Console application. When SDK debug logging is enabled, the SDK uses the OS_LOG_TYPE_DEBUG value. Make sure to disable logging in your application for release builds to the App Store.
For more information about unified logging, see Logging on Apple Developer.
Send a Test Push
Test Using Apple Push Notification Service
To test whether your app can receive a push directly from the Apple Push Notification Service (APNS), follow these steps.
Get the push token from the SDK. For testing and troubleshooting purposes, retrieve your device token from a running app by calling sfmc_deviceToken() and send the result to yourself via email, alert, or another method.
8.x
print(SFMCSdk.mp.deviceToken()??"error: no token - was UIApplication.shared.registerForRemoteNotifications() called?")
7.x
print(MarketingCloudSDK.sharedInstance().sfmc_deviceToken()??"error: no token - was UIApplication.shared.registerForRemoteNotifications() called?")
Trigger the APNS API directly from the command line if using a .p8 authentication key.
The following script points to the development APNS service by default. To trigger push from the APNS production server, change the endPoint to https://api.push.apple.com in the following script.
Note
#!/bin/bash# To get curl with HTTP/2 and openssl with ECDSA: run 'brew install curl-openssl'curl=/usr/local/opt/curl/bin/curl
openssl=/usr/local/opt/openssl/bin/openssl
--------------------------------------------------------------------------
deviceToken=#push token returned from MobilePush SDKauthKey=#path to your .p8 extension Auth Key FileauthKeyId=#the Key ID of the .p8 Auth Key FileteamId=#team id found in apple developer accountbundleId=#application bundle identifierendpoint=https://api.development.push.apple.com
read-r-d'' payload <<-'EOF'
{
"aps": {
"badge": 1,
"alert": {
"title": "TEST_PUSH_TITLE",
"subtitle": "TEST_PUSH_SUBTITLE",
"body": "TEST_PUSH_BODY"
},
"_sid": "SFMC"
}
}
EOF# --------------------------------------------------------------------------base64(){$openssl base64 -e-A|tr -- '+/''-_'|tr-d=}sign(){printf"$1"|$openssl dgst -binary-sha256-sign"$authKey"| base64
}time=$(date +%s)header=$(printf'{ "alg": "ES256", "kid": "%s" }'"$authKeyId"| base64)claims=$(printf'{ "iss": "%s", "iat": %d }'"$teamId""$time"| base64)jwt="$header.$claims.$(sign $header.$claims)"$curl--verbose\--header"content-type: application/json"\--header"authorization: bearer $jwt"\--header"apns-topic: $bundleId"\--data"$payload"\$endpoint/3/device/$deviceToken
If using a .p12 certificate (legacy), trigger the APNS API directly from the command line.
#!/bin/shexportDEVICE_TOKEN=#push token returned from MobilePush SDKexportBUNDLE_ID=#application bundle identifierexportCERT_PATH=#path to your push certificate and key, exported as a p12 fileexportCERT_PASSWORD=#password of your p12 file# sent your endpoint to prod or sandbox# sandbox MUST use a development push certificate# sandbox MUST use a push token from a debugging build of your app (run from# Xcode to a connected device)exportENDPOINT=https://api.push.apple.com/3/device
#export ENDPOINT=https://api.sandbox.push.apple.com/3/devicecurl-v\-d'{"_m": "TEST_MESSAGE_ID", "aps": {"alert": {"body": "TEST_PUSH_BODY", "title": "TEST_PUSH_TITLE", "subtitle": "TEST_PUSH_SUBTITLE"},"_sid": "SFMC"}}'\-H"apns-topic: ${BUNDLE_ID}"\--http2\--cert${CERT_PATH}:${CERT_PASSWORD}\
--cert-type P12 \${ENDPOINT}/${DEVICE_TOKEN}
If your device receives the push notification, you can assume that you've set up your application correctly. The setup includes creating a .p8 authentication key or .p12 certificate, building the app with the correct bundle ID, and using the appropriate provisioning profiles.
Note
Test Through Marketing Cloud Engagement
Note the environment (development or production APNS) in which the push was successfully delivered while sending a test push.
On the Engagement Administration page, point to the same environment under Sending Services > iOS Sending and send a push notification. Check if your device received the push notification.
Ensuring the selection of the correct APNS environment is crucial for the SDK to trigger push notifications to the appropriate APNS server. If you select the Development radio button, Engagement contacts the Sandbox APNS server. If you select the Production radio button, Engagement contacts the Production APNS server.
Note
Log SDK State Information
To retrieve a all of the information the SDK has and its current state, implement getSDKState() as shown in the following example.
8.x
print("SDK State = \(SFMCSdk.state())")
7.x
// display a JSON formatted, easily readable block of text describing the current status of the SDK.print("SDK State = \(MarketingCloudSDK.sharedInstance().sfmc_getSDKState()??"SDK State is nil")")
The SDK outputs a JSON string as shown in the following example.
Testing your app while connected to a corporate network can prevent your test device from receiving messages, especially if your IT team doesn't configure port accessibility. Ensure that your IT team unblocks the following TCP ports to facilitate communication between your test device and the APNS servers for MobilePush functionality.
TCP Port
Description
5223
Used by devices to communicate to the APNS servers
2195
Used to send notifications to the APNS servers
2196
Used by the APNS feedback service
443
Used as a fallback service for Wi-Fi devices when those devices can't communicate with the APNS service on port 5223
Review Additional Troubleshooting Guidance
Refer to the following articles when testing your app, or when troubleshooting why your devices aren't receiving messages or are receiving them sporadically.
The MobilePush SDK can coexist and work in the same app as other push vendor SDKs. However, we recommend checking with your other SDK vendors to ensure they also support a multi-push provider implementation. The following sections provide considerations for multiple push SDKs to successfully work together.
Common Issues With Multiple Push Provider (MPP)
MPP implementations often affect the following functionalities, hence preventing the SDK from behaving as expected.
Receiving Device Tokens
Receiving Push Messages
Without device tokens, the SDK doesn't register the device properly and Engagement is unable to send push notifications to the device. The SDK expects you to pass push notifications to the setNotificationRequest method. Doing so makes the SDK aware of the notifications and allows it to handle them accordingly (for example, tracking and URL handling).
Apple has specific delegate methods that the consuming application must implement to register with APNS and receive push notifications. Implementing multiple push providers can affect the previously mentioned functionality since other vendors can provide wrapper methods for registration and receiving the notifications. Consuming applications often listen to the wrapper methods instead of actual Apple-provided delegate methods. An example of a common issue is when registration with Apple is done for one push provider without setting the deviceToken for other push providers.
Handling MPP With MobilePush SDK
Method Swizzling is the process of changing the implementation of an existing selector at runtime. If Method Swizzling is enabled, other push providers automatically intercept all the application delegate methods, which differ from the normal flow in setting up the deviceToken and notification userinfo.
Method Swizzling can confuse MobilePush SDK users about how and where to set the SDK's required API methods because another provider is changing the implementation without their knowledge.
To determine if non-MobilePush SDK providers use Swizzling, check to see whether they don't use the following methods.
MobilePush SDK users can handle MPP implementations with and without Swizzling enabled.
With Swizzling Enabled
If Swizzling is enabled, implement the respective push provider’s delegate methods and set the following to the MobilePush SDK.
Configuration With Another Push Provider
Configure the SDK along with the other Push provider.
funcapplication(_ application:UIApplication, didFinishLaunchingWithOptions launchOptions:[UIApplication.LaunchOptionsKey:Any]?)->Bool{iflet options = launchOptions,let notification = options[UIApplication.LaunchOptionsKey.remoteNotification]as?[AnyHashable:Any]{self.notificationUserInfo = notification
}FirebaseApp.configure()Messaging.messaging().delegate =selfself.configureSFMCSdk()if#available(iOS 10.0,*){UNUserNotificationCenter.current().delegate =selflet authOptions:UNAuthorizationOptions=[.alert,.badge,.sound]UNUserNotificationCenter.current().requestAuthorization(
options: authOptions,
completionHandler:{_,_in})}else{let settings:UIUserNotificationSettings=UIUserNotificationSettings(types:[.alert,.badge,.sound], categories:nil)
application.registerUserNotificationSettings(settings)}
application.registerForRemoteNotifications()returntrue}@discardableResultfuncconfigureSFMCSdk()->Bool{let appID ="<your appID here>"let accessToken ="<your accessToken here>"let appEndpointURL ="<your appEndpoint here>"let mid ="<your account MID here>"#if DEBUGSFMCSdk.setLogger(logLevel:.debug)#endiflet appEndpoint =URL(string: appEndpointURL)!// To override the Keycahin accessibility attribute (default set by SDK: kSecAttrAccessibleWhenUnlockedThisDeviceOnly)SFMCSdk.setKeychainAccessibleAttribute(accessibleAttribute:kSecAttrAccessibleWhenUnlockedThisDeviceOnly)// To Override the Keychain Error to be considered fatal or not (Default value is true)SFMCSdk.setKeychainAccessErrorsAreFatal(errorsAreFatal:false)let mobilePushConfiguration =PushConfigBuilder(appId: appID).setAccessToken(accessToken).setMarketingCloudServerUrl(appEndpoint).setMid(mid).setInboxEnabled(true)// enable if needed by your application.setLocationEnabled(true)// enable if needed by your application.setAnalyticsEnabled(true)// enable if needed by your application.build()let completionHandler:(OperationResult)->()={ result inif result ==.success {self.setupMobilePush()}elseif result ==.error {}elseif result ==.cancelled {}elseif result ==.timeout {}}SFMCSdk.initializeSdk(ConfigBuilder().setPush(config: mobilePushConfiguration, onCompletion: completionHandler).build())returntrue
Handling DeviceToken
API: setDeviceToken(apnsToken)
// MARK: FireBaseMessaging Delegate/**
Set deviceToken to MarketingCloudSDK in the FCM delegate method when Swizzling is enabled.
DeviceToken must be set MANDATORILY to MarketingCloudSDK using`SFMCSdk.mp.setDeviceToken` API for Push notifications to be received through Mobile Push.
*/extensionAppDelegate:MessagingDelegate{funcmessaging(_ messaging:Messaging, didReceiveRegistrationToken fcmToken:String?){print("FCM Token", fcmToken ??"")SFMCSdk.requestPushSdk { mp inprint("SDK is operational")iflet apnsToken = messaging.apnsToken {print("Setting APNS token in MarketingCloudSDK")
mp.setDeviceToken(apnsToken)}else{print("fcm token is null")}print("SDK is not yet operational")}}}
Handling Notifications
When Swizzling is enabled in the other push provider, respective delegate methods are intercepted. For example, considering Firebase as the other push provider, when a push notification is received from Firebase, the payload received in the UNUserNotificationCenterDelegate's didReceive notification method is altered to receive a MessagingMessageInfo object. This payload alteration results in the message not being reported when passed to the SDK, as the payload expected by the SDK doesn't match.
Notification messages from other providers are displayed in the device’s notification center. However, any action on the notification message from the SDK (for example, URL handling and reporting) doesn't work.
Note
With Swizzling Disabled
To disable Swizzling, refer to the other push provider’s documentation. When Swizzling is disabled in the other push provider, the default AppDelegate methods are called.
Implement AppDelegate Methods
// Disable Swizzling in the other push provider used//registerForRemoteNotifications() method gets to this callbackfuncapplication(_ application:UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken:Data){SFMCSdk.requestPushSdk { mp in
mp.setDeviceToken(deviceToken)}}/**
MobilePush SDK: REQUIRED IMPLEMENTATION
*/funcapplication(_ application:UIApplication, didReceiveRemoteNotification userInfo:[AnyHashable:Any], fetchCompletionHandler completionHandler:@escaping(UIBackgroundFetchResult)->Void){SFMCSdk.requestPushSdk { mp in
mp.setNotificationUserInfo(userInfo)}completionHandler(.newData)}funcuserNotificationCenter(_ center:UNUserNotificationCenter, didReceive response:UNNotificationResponse, withCompletionHandler completionHandler:@escaping()->Void){SFMCSdk.requestPushSdk { mp in
mp.setNotificationRequest(response.notification.request)}completionHandler()}funcuserNotificationCenter(_ center:UNUserNotificationCenter, willPresent notification:UNNotification, withCompletionHandler completionHandler:@escaping(UNNotificationPresentationOptions)->Void){completionHandler([.banner,.list,.sound])}
Common Areas for Poor MPP Implementation
Common areas for poor implementation can include device registration, geolocation, and more.
This isn’t an exhaustive list.
Note
Registration
You must only make one call to a push SDK to register for push notifications. Otherwise, a single push notification can trigger multiple notification banners, alerts, or sounds. The MobilePush SDK gives the app developer the power to register.
Notification Settings
An app can invoke requestAuthorizationWithOptions and registerForRemoteNotifications multiple times. However, only the settings from the last call are used, as each successive call overwrites the previous settings.
Badging
There’s no way to guarantee the value of a badge.
Custom Payload Keys
If your implementation must distinguish between two notification providers, use custom keys or other payload-specific data to ensure that your app calls the correct SDK handler that supports multiple notification handlers.
Passing a third party’s notification to setNotificationRequest or setNotificationUserInfo is essentially a no-op call. The SDK only emits logs indicating the origin of the notification wasn’t from Engagement.
Geolocation
If you implement multiple SDKs that use location-enabled services, use only one SDK’s location enablement. Using more than one leads to unknown and unsupportable consequences. For example, the methods used by the other providers to interact with iOS CoreLocation services and enable location services are likely to affect each provider.
An app can monitor a limited number of geofences at any given time. This number depends on iOS version, device type, and other considerations. With multiple implementations competing for a limited resource, the user experience can suffer. Additionally, permissions needed to use location-enabled SDKs can overlap or conflict.
Feedback
Not all providers are able to detect if a device has been unregistered.
To see how notifications are handled using Firebase as a push provider, see the iOS LearningApp.
iOS Data Protection
iOS Data Protection affects the SDK as described in the following table.
iOS Data Protection Level
SDK Behavior
No protection
SDK works in the foreground and background
Complete until first user authentication
SDK works in the foreground and background after the first unlock
Complete unless open
SDK works in the foreground and background after the first unlock
Complete
SDK works only in the foreground after the device is unlocked
The MobilePush SDK requires access to files on the iOS Device file system. Some iOS Data Protection modes can prevent the SDK from accessing the needed files at certain times. During normal operation, the SDK must have access to files while running in the foreground and while running in the background. If the SDK can't access these files due to an iOS Data Protection mode, an error is logged and file access fails.
By default, the SDK sets the file protection type to NSFileProtectionCompleteUntilFirstUserAuthentication. With this file protection type, files are stored in an encrypted format on disk and can't be read from or written to until the user unlocks the device for the first time. As of version 8.0.9, the SDK continues to retain the default protection type (NSFileProtectionCompleteUntilFirstUserAuthentication). However, it also provides the capability to override the file protection type within the consuming application. You can choose different file protection types, such as NSFileProtectionComplete and NSFileProtectionCompleteUnlessOpen, based on your specific needs.
NSSQLiteErrorDomain errors can appear in logs if the FileProtectionType is NSFileProtectionComplete and the application goes to the background.
Note
Override FileProtectionType
The following example shows how you can override the file protection type.
For an additional example of overriding the file protection type, see the learning application.
Configuration Issues
If you configure iOS data protection such that the file system isn’t accessible during the SDK configuration call, the SDK retries the call for up to 5 seconds. This retry period allows time for a user to unlock the device and make the file system accessible. If the user doesn’t unlock the device within 5 seconds, an error object is returned describing the error, and the configuration call fails, returning false. In this case, the SDK isn't configured, and no access to SDK methods must be attempted until the configure method returns true. The error object returns the error code configureDatabaseAccessError.
Foreground and Background Operation Issues
Certain features of the SDK require access to the file system as the app transitions to the foreground or background. Foreground operations include retrieving messages from Engagement for inbox messaging, location messaging, and sending analytic information back to Engagement. Background operations include sending analytic information back to Engagement. If any of these features are enabled via configuration, then an appropriate iOS Data Protection mode must be selected for them to work correctly.
Troubleshoot Data Merge
For iOS applications upgraded from SDK versions 7.x to versions up to 8.0.6, the previous v7.x tags and attributes are retained on the device but not sent to the server. If an application doesn't reset or regenerate tags and attributes, the device sends empty tags and attributes to the system.
The following sections walk through the requirements for merging datasets successfully.
Using SPM, upgrade to the latest version of the MobilePush SDK for iOS and SFMCSDK for iOS.
Merge Data (Optional)
The merging tool offers two options to merge attributes and tags: automatic merging and manual merging. In some scenarios, you can choose to defer or avoid merging the datasets. The merging tool defaults to an "opted out" state if you don't implement either of the merging methods. In the opted out state, tags and attributes aren't merged from the version 7.x dataset to your current application's dataset.
Automatic Merging
The automatic merging option attempts to merge old data into the current dataset, with the current data taking precedence over data within the version 7.x dataset.
The following tables illustrate how automatic merging behaves and how data is merged.
In the following tables, key:value pairs are denoted using : as the separator.
Note
Attributes
Prior Dataset
Current Dataset
Merge Result
A:B
empty
A:B
empty
A:B
A:B
A:B, C:D
A:E
A:E, C:D
A:B
A: cleared
A: cleared
Tags
Prior Dataset
Current Dataset
Merge Result
SHIRTS
empty
SHIRTS
empty
PANTS
PANTS
SHIRTS
PANTS
SHIRTS, PANTS
SHIRTS
SHIRTS, PANTS
SHIRTS, PANTS
The following code snippets show you how to configure the SDK to attempt an automatic merge.
To ensure the completion callback passed into setAutoMergePolicy is set before SDK initialization, place the following code snippets before SDK initialization.
The manual merge option enables you to receive both the prior data and the current data in a callback, providing the opportunity to choose what data ultimately ends up in the final dataset.
You can decide what attributes and tags are set in the current dataset. However, to set attributes and tags accordingly, you must retain the data until the SDK is initialized.
Access to the tags and attributes for versions 7.x and 8.x is provided before SDK initialization.
Important
Swift
classExampleDelegate:UIResponder,UIApplicationDelegate{var setTagsAndAttributes:(()->())?=nil// ...}// ...SFMCSdk.setManualMergePolicy(withHandler:{(v7, v8)inself.setTagsAndAttributes ={let attributes:[String:String]=// e.g. v8["attributes"] as! [String : String]SFMCSdk.identity.setProfileAttributes([ModuleName.push : attributes])let tags:[String]=// e.g. v8["tags"]SFMCSdk.requestPushSdk { mp in
mp.addTags(tags)}}}// ...let completionHandler:(OperationResult)->()={ result in// ...if result ==.success {// ...if(SFMCSdk.mp.getStatus()==.operational){self.setTagsAndAttributes?()}// ...}}// ...SFMCSdk.initializeSdk(ConfigBuilder().setPush(config: configuration, onCompletion: completionHandler).build())
If you must run the merge tool again, you can attempt the merge multiple times.
Reattempting merges doesn’t roll back the current dataset but enables you to regain access to the data within the old version 7.x dataset.
Swift
let appId =// your app IDlet resetSuccess:Bool=SFMCSdk.resetDataPolicy(appId: appId)if(resetSuccess){print("reset succeeded")}
Objective-C
NSString *appId = // your app ID
BOOL resetSuccess = [SFMCSdk resetDataPolicyWithAppId:appId];
if(resetSuccess) {
NSLog(@"reset succeeded");
}
Keychain Crash
The following troubleshooting guidance applies only to MobilePush iOS SDK versions up to 8.0.13.
Important
Fatal Keychain Access exceptions occur when an application with an active MobilePush SDK integration tries to access Keychain on a locked device secured with Face ID or passcode-based authentication. iOS Data Protection modes prevent the MobilePush SDK from accessing these files.
The following sections describe common Keychain Access exceptions and provide guidance on resolving them.
Doing so logs the exception to the console instead of causing the application to crash.
By default, the SDK sets setKeychainAccessErrorsAreFatal to true.
Note
Unknown Status Code (-34018)
You can encounter the following error message that indicates a keychain access issue along with an unknown status code (-34018).
Terminating app due to uncaught exception 'com.salesforce.security.keychainException', reason: 'dictionaryItemFromKeychain: Error attempting to look up keychain item: Unknown status code (-34018)'
To resolve this issue, enable Keychain Sharing in Xcode's Signing & Capabilities. While enabling Keychain Sharing, you don't need to add identifiers specific to the SDK.
Related Items
For an example of an ideal MobilePush iOS SDK implementation, review the iOS LearningApp.
Not all pieces of code used in the LearningApp are mandatory. Depending on your app, you can decide which parts to use or replicate and which ones to ignore.
Note
MarketingCloudSDK.bundle Inclusion Crash
The following troubleshooting guidance applies only to MobilePush iOS SDK versions up to 8.0.13. Starting version 8.1.0, the SDK automatically includes the bundle in applications, eliminating the need for manual addition.
Important
When upgrading to the latest version of the SDK, changes to MarketingCloudSDK.bundle are expected. If you don't copy the right versions, your app can crash with exceptions as the older versions of MarketingCloudSDK.bundle don't have the required resources.
When you don't include the latest MarketingCloudSDK.bundle in your app, you can encounter the following exceptions.
NSInvalidArgumentException
Reason: +entityForName: nil is not a legal NSManagedObjectContext parameter searching for entity name 'SFMCEndpointConfigurationEntity'
NSInternalInconsistencyException
Reasons:
'NSFetchRequest could not locate an NSEntityDescription for entity name 'SFMCEventConfigurationEntity''
'Cannot create an NSPersistentStoreCoordinator with a nil model'
To resolve these exceptions, upgrade to the latest version of the SDK and then follow these steps.
Remove the existing MarketingCloudSDK.bundle from Xcode under Build phases > Copy Resources Bundle.
Based on your integration method, add the latest MarketingCloudSDK.bundle.
If you're using SPM as a dependency manager, following the instructions provided in the iOS Migration Guide.
For every upgrade of the SDK, we recommend pulling MarketingCloudSDK.bundle each time to ensure your app is using the latest bundle.
Note
Silent Push Notification
Silent push notifications are delivered without an alert message or sound, typically to trigger updates to the app UI or background operations. A silent push notification wakes your app from a "Suspended" or "Not Running" state to update content or run certain background tasks without notifying users.
To use silent push notifications to trigger background tasks, you must configure your app to receive notifications even when it's in the background. To do so, navigate to the Signing & Capabilities pane on Xcode, and add the Background Modes capability to the main app target. Also ensure that you select the Remote notifications checkbox.
To handle silent push notifications, the app must implement the application:didReceiveRemoteNotification:fetchCompletionHandler: application delegate method. For more information, see Apple's documentation on Pushing background updates to your app.
Troubleshoot Push Delivery Analytics
When encountering issues with push delivery analytics, consider these common problems and their resolutions:
Missing Push Delivery Analytics
First confirm that push delivery analytics is enabled in the Engagement UI. If disabled, your Engagement admin must enable it for the SDK to send delivery events.
If push delivery events and analytics aren't appearing in your Engagement reports, verify whether you're sending supported message types. Push delivery analytics are only available for Push and Alert + Inbox messages. In-App, Geofence, Proximity, and silent pushes aren't tracked.
Multiple Push Provider Implementation Problems
If you're using multiple push providers, ensure that no fields or keys are removed from the push payload before passing it to SFMCNotificationService, which your NotificationService class in the service extension inherits from. The SDK requires the complete push payload to process push delivery events. If any keys or fields are missing, the SDK logs a warning and doesn't process the push delivery event.