Category: API Deprecation

  • SwiftUI .tabItem deprecated in iOS 18.1 -> replace it with new Tab

    In the newest Xcode, you might see a deprecation warning if you try to use .tabItem view modifier.

    💡

    ‘tabItem’ will be deprecated in a future version of iOS: Use Tab (title:image:value:content:) and related initializers instead

    As shown on the Apple Developer documentation:

    You can easily fix this by using the new Tab view:

    You can also easily add a badge (that shows a number or a character text), and use the value parameter to control which tab is currently activated:

  • 「ITMS-91053: Missing API declaration」アプリのプライバシーレポートでのAPI使用宣言(iOSアプリを審査に提出したら)

    Qiita: https://qiita.com/mashunzhe/items/d2c035c0d4794a6bf211

    Medium (English version): https://medium.com/@MszPro/itms-91053-missing-api-declaration-for-accessing-userdefaults-timestamps-other-apis-d5c0cbf84a5e

    App Storeにアップデートを提出しようとして、以下のメールを受け取ったことはありますか?

    image.png

    WWDC 2023で明らかになったように、UserDefaultsのようなAPIを使用する場合は、プライバシーレポートを作成する必要があります。2024年5月1日から、このようなプライバシー宣言なしで新しいアプリのビルドをアップロードすることは許可されません。
    プライバシーレポートを作成するには、以下の手順に従ってください:

    まず、プロジェクトに新しいファイルを作成します:

    image.png

    そのファイルのタイプは「App Privacy」と呼ばれます

    image.png

    このファイルが適用されるターゲットに対してファイルをリンクする必要があります。例えば、UserDefaultsをすべてのアプリターゲット内で使用している場合、このファイルをそれら全てに適用します:

    image.png

    アプリのプライバシー設定内には、主に4つのカテゴリーがあります:

    image.png

    注:いつでも、生のキーや英語の説明タイトルの間で切り替えることができます。白いエリアを右クリックして生の値の切り替えを使用してください。

    image.png

    以下は、私のアプリがユーザーを追跡せず、ユーザーIDをユーザー登録に使用するが追跡には使用しない、そしてUserDefaultsフレームワークを使用してメインアプリとウィジェット間で設定を保存する場合の、完成したファイルの例です。

    image.png

    プライバシーがアクセスしたAPIのタイプ

    これは、UserDefaultsやその他のAPIを使用する理由を宣言する必要がある場所です。宣言する必要があるAPIの完全なリストはこちらです:
    https://developer.apple.com/documentation/bundleresources/privacy_manifest_files/describing_use_of_required_reason_api

    プライバシーがアクセスしたAPIのタイプを選択してエンターキーを押し、新しい辞書エントリを作成します。

    image.png

    この項目を展開し、エンターキーを押してプロパティを追加します。2つのプロパティが必要で、「プライバシーがアクセスしたAPIタイプ」はAPIのタイプを宣言し、「プライバシーがアクセスしたAPI理由」はアプリがそのデータが必要な理由の配列です。

    image.png

    例えば、私のアプリがUserDefaultsを使用する場合、アクセスしたAPIタイプとしてUser Defaultsを入れます。

    image.png

    その後、このデータへのアクセス理由のコードを記入します。各APIタイプごとに異なるコードのセットがあります:

    UserDefaults

    UserDefaultsを使用してユーザー設定を保存する場合、理由を宣言する必要があります。APIタイプは NSPrivacyAccessedAPICategoryUserDefaults と呼ばれます。

    CA92.1

    アプリ自身だけがアクセス可能な情報を読み書きするためにユーザーデフォルトにアクセスします。
    注意:このコードを宣言する場合、アプリグループ内でUserDefaultsの値を共有することはできません(アプリとウィジェット間でデータを共有することはできません)

    1C8F.1

    アプリ自体と同じアプリグループのメンバーであるアプリ、アプリ拡張、App Clipsのみがアクセス可能な情報を読み書きするためにユーザーデフォルトにアクセスします。
    注意:この理由でも、同じアプリグループ外のアプリ、アプリ拡張、App Clipsがアクセスできる情報を書き込むことは許可されません。

    C56D.1

    サードパーティのSDKがアプリが使用するためのユーザーデフォルトAPIを囲むラッパー機能を提供しており、アプリがラッパー機能を呼び出すときのみユーザーデフォルトAPIにアクセスします。
    注意:この理由でアクセスされた情報、または派生した情報は、サードパーティSDK自身の目的のために使用されたり、サードパーティSDKによってデバイス外に送信されることはできません。

    例えば、私のアプリがUserDefaultsを使用して、メインiOSアプリとウィジェット間でユーザーの現在の都市を共有し、天気を表示する場合、1C8F.1を使用する必要があります。

    image.png

    ウィジェットやアプリグループを持っていない場合は、コードCA92.1を使用できますが、将来的にはコードを1C8F.1に変更することを忘れないでください。そうしないと、UserDefaultsのデータがアプリ自身にのみ制限される可能性があります。

    ファイルタイムスタンプAPI

    これらは、ファイルのタイムスタンプにアクセスするためのAPIであり、creationDatemodificationDateなどを含みます。

    APIタイプはNSPrivacyAccessedAPICategoryFileTimestampと呼ばれます。

    APIメソッド

    creationDate、modificationDate、fileModificationDate、contentModificationDateKey、creationDateKey、getattrlist(:::::)、getattrlistbulk(:::::)、fgetattrlist(:::::)、stat、fstat(::)、fstatat(::::)、lstat(::)、getattrlistat(:::::_:)

    宣言コード

    DDA9.1

    デバイスを使用している人にファイルのタイムスタンプを表示したい場合。
    注:この理由を宣言すると、情報はデバイス外に送信されません。

    C617.1

    アプリコンテナ、アプリグループコンテナ、またはアプリのCloudKitコンテナ内のファイルのタイムスタンプ、サイズ、またはその他のメタデータにアクセスします。

    3B52.1

    ユーザーが特にアクセスを許可したファイルやディレクトリのタイムスタンプ、サイズ、またはその他のメタデータにアクセスします。例えば、ドキュメントピッカービューコントローラーを使用する場合などです。

    0A2A.1

    サードパーティのSDKがアプリが使用するためのファイルタイムスタンプAPIの周りにラッパー機能を提供しており、アプリがラッパー機能を呼び出すときのみファイルタイムスタンプAPIにアクセスします。
    要約すると、システムネイティブのファイルピッカーを使用してユーザーが選択したファイルのみを読み取る場合は3B52.1を使用します。情報を表示するだけで保存やアップロードを行わない場合はDDA9.1を使用します。アプリ、アプリグループ、またはCloudKit内でこの情報にアクセスして使用する場合はC617.1を使用します。

    私のアプリは、ユーザーが(iOSシステムネイティブのファイルピッカーを使用して)選択したファイルのタイムスタンプにのみアクセスするため、以下の設定を行いました:

    image.png

    システム起動時間API

    APIタイプは NSPrivacyAccessedAPICategorySystemBootTime です。

    APIメソッド

    systemUptime
    mach_absolute_time()

    35F9.1

    アプリ内で発生したイベント間の経過時間を測定したり、タイマーを有効にするための計算を実行するために、システム起動時間にアクセスします。このデータをデバイス外に送信することはできません。

    8FFB.1

    UIKitやAVFAudioフレームワークに関連するイベントなど、アプリ内で発生したイベントの絶対タイムスタンプを計算します。

    3D61.1

    ユーザーが提出を選択したバグレポートにおいて。システム起動時間情報はレポートの一部としてユーザーに顕著に表示されなければなりません。

    ディスクスペースAPI

    APIタイプは NSPrivacyAccessedAPICategoryDiskSpace です。

    APIメソッド

    volumeAvailableCapacityKey
    volumeAvailableCapacityForImportantUsageKey
    volumeAvailableCapacityForOpportunisticUsageKey
    volumeTotalCapacityKey
    systemFreeSize
    systemSize
    statfs(::)
    statvfs(::)
    fstatfs(::)
    fstatvfs(::)
    getattrlist(::::🙂
    fgetattrlist(::::🙂
    getattrlistat(::::::)

    85F4.1

    デバイスを使用している人にディスクスペース情報を表示します(表示のみで、この情報をデバイス外に送信することは含まれません)。

    E174.1

    ファイルを書き込むための十分なディスクスペースがあるかを確認する、またはディスクスペースが少ない場合にアプリがファイルを削除できるようにするためにディスクスペースが低いかをチェックします。

    7D9E.1

    バグレポートに使用されますが、ユーザーが提出するかどうかを選択するオプショナルな情報でなければなりません。

    B728.1

    健康研究アプリで、このAPIカテゴリにアクセスして、研究データ収集に影響を与える低ディスクスペースを研究参加者に知らせます。

    アクティブなキーボードのアクセスリスト

    APIタイプは NSPrivacyAccessedAPICategoryActiveKeyboards です。

    APIメソッド

    activeInputModes

    3EC4.1

    あなたのアプリがカスタムキーボードアプリであり、デバイス上でアクティブなキーボードを特定するためにこのAPIカテゴリにアクセスするときに使用します。

    54BD.1

    デバイスを使用している人に正しいカスタマイズされたユーザーインターフェースを提示するためにアクティブなキーボード情報にアクセスします。アプリはテキストの入力や編集のためのテキストフィールドを持ち、ユーザーに観察可能な方法でアクティブなキーボードに基づいて異なる振る舞いをする必要があります。

    プライバシー トラッキング有効 (Privacy Tracking Enabled)

    このブール値は、アプリがユーザー情報をトラッキング目的で使用するかどうかを示します。

    プライバシー トラッキングドメイン (Privacy Tracking Domains)

    これは、ドメインホスト名の文字列値の配列を含む文字列配列です。これらはトラッキング関連目的で使用されるドメインです。トラッキングに使用されないドメインを記載しないでください。なぜなら、ユーザーがアプリにトラッキングしないように求めた場合、これらのドメインへのネットワークリクエストは失敗するからです。

    プライバシーナビゲーションラベルタイプ (Privacy Nutrition Label Types)

    ここでは、アプリが収集するデータのタイプと、これらを収集する理由を宣言します。プライバシーナビゲーションラベルタイプを選択してエンターキーを押すと、必要な情報を含む新しいエントリが自動的に作成されます。

    image.png

    収集データタイプのドロップダウンメニューを選択できます。これは、私たちが収集するデータのタイプを示します。例えば、ここではユーザーのメールアドレスを選択できます。

    image.png

    データタイプの完全なリストはこちらにあります:https://developer.apple.com/documentation/bundleresources/privacy_manifest_files/describing_data_use_in_privacy_manifests

    次に、データがユーザーにリンクされているかどうかを回答します(例えば、メールアドレスがユーザープロファイルにリンクされている場合、これをYESに設定する必要があります)。そして、データがトラッキング目的で使用されているかどうか。

    その後、コレクション目的の配列に、アプリがこの情報を必要とする理由を追加します(例えば、ユーザーアカウントの登録にメールアドレスが必要な場合、アプリ機能 (App Functionarlity) を選択できます。

    image.png

    これは、App Store Connectでプライバシーに関する質問に答える方法と似ています。

  • ITMS-91053: Missing API declaration — for accessing UserDefaults, timestamps & other APIs

    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.

    Privacy Accessed API Types (Necessary)

    This is where you need to declare the reason for using UserDefaults and other APIs. The full list of API that you need to declare is here: https://developer.apple.com/documentation/bundleresources/privacy_manifest_files/describing_use_of_required_reason_api

    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`

    API methods:

    creationDate modificationDate fileModificationDate contentModificationDateKey creationDateKey getattrlist(_:_:_:_:_:) getattrlistbulk(_:_:_:_:_:) fgetattrlist(_:_:_:_:_:) stat fstat(_:_:) fstatat(_:_:_:_:) lstat(_:_:) getattrlistat(_:_:_:_:_:_:)

    Declaration codes:

    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.

    Disk space APIs

    volumeAvailableCapacityKey volumeAvailableCapacityForImportantUsageKey volumeAvailableCapacityForOpportunisticUsageKey volumeTotalCapacityKey systemFreeSize systemSize statfs(_:_:) statvfs(_:_:) fstatfs(_:_:) fstatvfs(_:_:) getattrlist(_:_:_:_:_:) fgetattrlist(_:_:_:_:_:) getattrlistat(_:_:_:_:_:_:)

    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.

    A full list of the data types is located here: https://developer.apple.com/documentation/bundleresources/privacy_manifest_files/describing_data_use_in_privacy_manifests

    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.

    Official WWDC session video

    Describing data use in privacy manifests | Apple Developer DocumentationDeclare the data collected by your app or by third-party SDKs.developer.apple.com

    IOSIos Programming