Have you tried to submit an update to App Store and received the following email?
It is known from the WWDC 2023 that you have to create a privacy report when you use APIs like UserDefaults. Starting from May 1, 2024, uploading new builds of apps without such a privacy declaration will not be allowed.
To create a privacy report, follow these steps:
First, create a new file in your project:
The type of the file is called App Privacy
You should link the file against the target that this file applies to. For example, if I use UserDefaults within all my app targets, I will apply this file to all of them:
There are 4 main categories within the app privacy configuration:
Note: at any time, you can switch between the raw key values and the English descriptive title by right clicking the white area and use the raw value toggle:
Here is an example of the completed file, where my app does not track the user, uses the User ID for user registration (but does not use it for tracking), and uses UserDefaults framework to store preferences across my main app and widgets.
Tap to select the Privacy Accessed API Types and hit enter to create a new dictionary entry.
Now, expand this item and hit enter to add the property. Two of them are needed, where `Privacy Accessed API Type` declares the type of API, and `Privacy Accessed API Reasons` is an array of the reason of why your app needs that data.
For example, if my app uses UserDefaults you will put User Defaults as the accessed API type.
You will then put the code of the reason why you access this data. For each API Type, there is a different set of codes:
UserDefaults
If you use UserDefaults to store user preferences, you need to declare a reason. The API type is called `NSPrivacyAccessedAPICategoryUserDefaults`
CA92.1Access user defaults to read and write information that is only accessible to the app itself.
Note: if you declare this code, you cannot share the UserDefaults value within an app group (you cannot share data between your app and widgets)
1C8F.1Access user defaults to read and write information that is only accessible to the apps, app extensions, and App Clips that are members of the same App Group as the app itself.
Note: This reason also does not permit writing information that can be accessed by apps, app extensions, or App Clips outside the same App Group.
C56D.1Third-party SDK is providing a wrapper function around user defaults API(s) for the app to use, and you only access the user defaults APIs when the app calls your wrapper function.
Note: Information accessed for this reason, or any derived information, may not be used for your third-party SDK’s own purposes or sent off-device by your third-party SDK.
For example, if my app uses UserDefaults to share the user current city for displaying whether, between the main iOS app and the widget, I need to use 1C8F.1
If you do not have a widget or an app group, you can use the code CA92.1 , but in the future, remember to change the code to `1C8F.1`, otherwise the UserDefaults data might be restricted to only your app itself.
File timestamp APIs
These are the APIs to access the timestamps of a file, including the creationDate, modificationDate, etc.
The API type is called: `NSPrivacyAccessedAPICategoryFileTimestamp`
DDA9.1You are looking to display file timestamps to the person using the device.
Note: if you declare this reason the information may not be sent off-device.
C617.1Access the timestamps, size, or other metadata of files inside the app container, app group container, or the app’s CloudKit container.
3B52.1Access the timestamps, size, or other metadata of files or directories that the user specifically granted access to, such as using a document picker view controller.
0A2A.1Declare this reason if your third-party SDK is providing a wrapper function around file timestamp API(s) for the app to use, and you only access the file timestamp APIs when the app calls your wrapper function.
To summarize, use 3B52.1 if you are reading only the files picked by the user using the system native file picker. Use DDA9.1 if you are only showing the information and not storing or uploading it. Use C617.1 if you are accessing and using this information within the app, app group, or CloudKit.
My app only accesses timestamps of the files picked by the user (using the iOS system native file picker), so I have set the following:
System boot time APIs
systemUptime mach_absolute_time()
The API type is `NSPrivacyAccessedAPICategorySystemBootTime`
35F9.1Access the system boot time in order to measure the amount of time that has elapsed between events that occurred within the app or to perform calculations to enable timers. You cannot send this data off this device.
8FFB.1 Calculate absolute timestamps for events that occurred within your app, such as events related to the UIKit or AVFAudio frameworks.
3D61.1In bug report that the person chooses to submit. The system boot time information must be prominently displayed to the person as part of the report.
The API type is `NSPrivacyAccessedAPICategoryDiskSpace`
85F4.1Display disk space information to the person using the device (display only, not including sending this information off the device)
E174.1Check whether there is sufficient disk space to write files, or to check whether the disk space is low so that the app can delete files when the disk space is low.
7D9E.1Used in bug report. But needs to be optional information selected by the user whether to submit or not.
B728.1Health research app, and you access this API category to detect and inform research participants about low disk space impacting the research data collection.
Access list of active keyboards
activeInputModes
The API type is `NSPrivacyAccessedAPICategoryActiveKeyboards`
3EC4.1Used when your app is a custom keyboard app, and you access this API category to determine the keyboards that are active on the device.
54BD.1Access active keyboard information to present the correct customized user interface to the person using the device. The app must have text fields for entering or editing text and must behave differently based on active keyboards in a way that is observable to users.
Privacy Tracking Enabled
This boolean value indicates whether your app uses user information for tracking.
Privacy Tracking Domains
This is a string array containing an array of String values (of domain hostnames). These are the domains used for tracking related purposes. Do not put domains that are not used for tracking, since the network requests to these domains will fail if the user has asked the app not to track.
Privacy Nutrition Label Types
Here you will declare the type of the data your app collects and the reason for collecting these. If you select the `Privacy Nutrition Label Types` and hit enter, a new entry will be automatically created with the required information.
Now, we can select the dropdown menu of the Collected Data Type , which indicates the type of data we collect. For example, here we can select user email.
Now, you will answer whether the data is linked to the user (for example, in the case of an email address, if it is linked to the user’s profile, you should set this to YES). And whether the data is used for tracking.
Then, in the Collection Purposes array, you will add reasons why your app needs this information. (for example, if the user account registration requires email, you can select App Functionality .
This is similar to how you answer the privacy questions on App Store Connect.