← Todos los articulos

Análisis profundo del manifiesto de privacidad: qué cuenta como recolección de datos

Desde el 1 de mayo de 2024, toda app y SDK de terceros subido a App Store Connect ha necesitado un manifiesto de privacidad que declare su uso de “APIs con razón requerida”, su comportamiento de seguimiento y los tipos de datos recolectados1. El manifiesto es una lista de propiedades (PrivacyInfo.xcprivacy) que App Store ingiere al momento del envío, valida contra una superficie conocida de APIs sensibles a la privacidad y muestra en la etiqueta nutricional de privacidad orientada al usuario. Las apps que omiten el manifiesto, o que usan una API sensible a la privacidad sin declarar una razón aprobada, son rechazadas en el envío con ITMS-91053 o códigos relacionados2.

La mayoría de los equipos tratan el manifiesto como una tarea de cumplimiento única: lo escriben, lo envían y nunca más lo miran. El manifiesto es más que eso. Es un contrato estructurado entre la app y Apple que codifica lo que la app hace con los datos privados, y es el único lugar donde este contrato existe en forma legible por máquina. Leerlo cuidadosamente revela qué considera Apple sensible a la privacidad (la superficie es más amplia de lo que la mayoría de los desarrolladores espera), qué ve realmente el usuario en la etiqueta nutricional (más granular de lo que la mayoría de los equipos cree) y qué deben divulgar los SDKs de terceros (una obligación real, no una cortesía).

TL;DR

  • El manifiesto de privacidad tiene cuatro secciones de nivel superior: NSPrivacyTracking, NSPrivacyTrackingDomains, NSPrivacyCollectedDataTypes y NSPrivacyAccessedAPITypes3.
  • La lista de APIs con razón requerida cubre cinco categorías iniciales: marca de tiempo de archivo, tiempo de arranque del sistema, espacio en disco, teclados activos y User Defaults. Cada categoría tiene una lista cerrada de códigos de razón aprobados; las apps deben elegir uno o reescribir el código para evitar la API4.
  • El seguimiento se define de forma restringida: vincular datos del usuario con datos de otras empresas para publicidad o compartirlos con corredores de datos. Si NSPrivacyTracking es true, todo dominio usado para seguimiento debe aparecer en NSPrivacyTrackingDomains3.
  • Los SDKs de terceros deben enviar sus propios manifiestos. El manifiesto de la app se fusiona con los manifiestos de todos los SDKs vinculados al momento del envío; la falta de manifiestos de SDKs en la lista publicada por Apple bloquea la app5.
  • El mayor descuido: el acceso a UserDefaults siempre cuenta como una llamada a una API con razón requerida. Un UserDefaults.standard.set(...) estándar requiere un código de razón declarado.

Las cuatro secciones

Un archivo PrivacyInfo.xcprivacy completo tiene cuatro claves de nivel superior3. La estructura es una lista de propiedades, editada como XML en formato bruto o a través del editor de manifiesto de privacidad de Xcode.

NSPrivacyTracking (booleano)

Declara si la app o el SDK rastrea al usuario a través de apps y sitios web de otras empresas. La definición semántica se alinea con App Tracking Transparency: vincular datos del usuario con datos de otras empresas con el propósito de publicidad dirigida, entrega de publicidad dirigida o compartir datos del usuario con corredores de datos6.

Si NSPrivacyTracking es true, todo dominio usado para seguimiento debe aparecer en la lista NSPrivacyTrackingDomains. Si es false, la lista se omite (o queda vacía).

La definición restringida es importante. Muchas apps que muestran anuncios (a través de SKAdNetwork de Apple o SDKs de anuncios sin seguimiento) pueden declarar NSPrivacyTracking como false. El seguimiento es la vinculación con datos externos, no la visualización de anuncios.

NSPrivacyTrackingDomains (arreglo de cadenas)

La lista de dominios que la app o el SDK contacta con fines de seguimiento. Las apps que declaran NSPrivacyTracking como true deben enumerar aquí cada endpoint de seguimiento.

La lista se aplica en tiempo de ejecución mediante el Informe de privacidad de la app: si la app contacta un dominio que está marcado como de seguimiento pero no declarado, el Informe de privacidad de la app expone la discrepancia al usuario. Las violaciones repetidas arriesgan la eliminación de App Store.

NSPrivacyCollectedDataTypes (arreglo de diccionarios)

La declaración estructurada de recolección de datos que alimenta la etiqueta nutricional de privacidad de App Store3. Cada entrada describe un tipo de dato que la app recolecta, con subclaves:

  • NSPrivacyCollectedDataType: el tipo de dato de la lista cerrada de Apple (por ejemplo, NSPrivacyCollectedDataTypeName, NSPrivacyCollectedDataTypeEmailAddress, NSPrivacyCollectedDataTypeCrashData).
  • NSPrivacyCollectedDataTypeLinked: booleano, si el dato está vinculado a la identidad del usuario.
  • NSPrivacyCollectedDataTypeTracking: booleano, si el dato se usa para seguimiento.
  • NSPrivacyCollectedDataTypePurposes: arreglo, los propósitos para los cuales se recolecta el dato (analítica, funcionalidad de la app, publicidad, etc.).

Esta sección es la fuente de verdad para la etiqueta nutricional de privacidad. Las categorías “Datos usados para rastrearte” y “Datos vinculados a ti” de la etiqueta nutricional se calculan a partir de estos indicadores. Las declaraciones inexactas producen etiquetas nutricionales inexactas y arriesgan acciones de cumplimiento por parte de App Store.

NSPrivacyAccessedAPITypes (arreglo de diccionarios)

La declaración de APIs con razón requerida. Cada entrada empareja una categoría de API con razón requerida con un conjunto de códigos de razón aprobados4.

<key>NSPrivacyAccessedAPITypes</key>
<array>
    <dict>
        <key>NSPrivacyAccessedAPIType</key>
        <string>NSPrivacyAccessedAPICategoryUserDefaults</string>
        <key>NSPrivacyAccessedAPITypeReasons</key>
        <array>
            <string>CA92.1</string>
        </array>
    </dict>
    <dict>
        <key>NSPrivacyAccessedAPIType</key>
        <string>NSPrivacyAccessedAPICategoryFileTimestamp</string>
        <key>NSPrivacyAccessedAPITypeReasons</key>
        <array>
            <string>C617.1</string>
        </array>
    </dict>
</array>

Las razones son listas cerradas. La app elige una o más de la lista publicada por Apple por categoría; las cadenas arbitrarias son rechazadas en el envío.

Las cinco categorías de API con razón requerida

La lista inicial de Apple de 2024 definió cinco categorías de API que requieren una razón declarada4:

NSPrivacyAccessedAPICategoryFileTimestamp

Se activa con cualquier API que devuelva la hora de creación, modificación o acceso de un archivo. Puntos de entrada comunes: URL.resourceValues(forKeys: [.creationDateKey, ...]), FileManager.attributesOfItem(atPath:), stat(), fstat(), lstat(). Las cuatro razones aprobadas4:

  • DDA9.1. Mostrar marcas de tiempo de archivos al usuario del dispositivo. La información a la que se accede por esta razón no puede enviarse fuera del dispositivo.
  • C617.1. Acceder a metadatos de archivos (marcas de tiempo, tamaño, etc.) para archivos dentro del contenedor de la app, contenedor del grupo de la app o contenedor de CloudKit.
  • 3B52.1. Acceder a metadatos de archivos para archivos o directorios a los que el usuario ha otorgado acceso explícito (selector de documentos, etc.).
  • 0A2A.1. Envoltorios de SDKs de terceros que acceden a APIs de marca de tiempo de archivo solo cuando la app llama al envoltorio. Solo para SDKs.

La mayoría de las apps usan C617.1 (acceso al contenedor propio) para la gestión interna de archivos. Las apps que muestran fechas de archivos en la UI orientada al usuario usan DDA9.1. Las apps que leen archivos otorgados por el usuario (selector de documentos, destinos de extensión de compartir) usan 3B52.1. Los autores de SDKs usan 0A2A.1 exclusivamente.

NSPrivacyAccessedAPICategorySystemBootTime

Se activa con mach_absolute_time(), mach_continuous_time() y APIs relacionadas de tiempo de actividad. La preocupación de privacidad: el tiempo de arranque del sistema es una señal con huella digital que puede usarse para identificar el dispositivo a través de reinstalaciones. Las tres razones aprobadas4:

  • 35F9.1. Acceder al tiempo de arranque del sistema para medir intervalos de tiempo entre eventos de la app o para habilitar temporizadores.
  • 8FFB.1. Acceder al tiempo de arranque del sistema para calcular marcas de tiempo absolutas de eventos dentro de la app.
  • 3D61.1. Agregar información del tiempo de arranque del sistema en un informe de error opcional que el usuario elige enviar.

La mayoría de las apps usan 35F9.1 para medir el rendimiento. 8FFB.1 cubre los casos en los que la app deriva marcas de tiempo de eventos a partir del tiempo de arranque (relativo a la sesión del dispositivo). Ten en cuenta que Date() y Date.now no activan esta categoría; usan una fuente de tiempo distinta. La categoría cubre específicamente las llamadas de la familia mach_*_time.

NSPrivacyAccessedAPICategoryDiskSpace

Se activa con APIs que devuelven la capacidad del disco o el espacio libre, incluyendo URL.resourceValues(forKeys: [.volumeAvailableCapacityKey, ...]) y las APIs de atributos del sistema de archivos de NSFileManager. La preocupación de privacidad: los patrones de espacio en disco son una señal con huella digital. Las cuatro razones aprobadas4:

  • 854F.1. Mostrar información del espacio en disco al usuario del dispositivo, ya sea en unidades de datos o en unidades de tiempo de medio.
  • E174.1. Verificar el espacio en disco al escribir archivos o para gestionar el espacio en disco bajo (decidir si descargar un activo, limpiar archivos en caché).
  • 7D9E.1. Incluir información del espacio en disco en un informe de error opcional que el usuario elige enviar.
  • B728.1. Apps de investigación de salud que detectan e informan a los participantes sobre el espacio en disco bajo que afecta la recolección de datos del estudio.

NSPrivacyAccessedAPICategoryActiveKeyboards

Se activa con UITextInputMode.activeInputModes. Las apps que leen esta lista (típicamente para localizar el comportamiento o detectar el idioma de entrada) deben declarar una razón. Las dos razones aprobadas4:

  • 3EC4.1. Una app de teclado personalizado que determina los teclados activos en el dispositivo.
  • 54BD.1. Acceder a información de teclados activos para personalizar la interfaz de usuario en consecuencia (típicamente para UX consciente del idioma de entrada).

La mayoría de las apps no necesitan esta categoría. Si tu código llama a activeInputModes indirectamente a través de una biblioteca de terceros, el manifiesto de esa biblioteca lo declara.

NSPrivacyAccessedAPICategoryUserDefaults

La categoría que atrapa a casi todas las apps. Cualquier acceso a UserDefaults (UserDefaults.standard, defaults de grupo de app a través de init(suiteName:), llamadas individuales a set/get) activa el requisito7. Las cuatro razones aprobadas4:

  • CA92.1. Acceder a user defaults para leer/escribir datos exclusivos de la app misma (o de una extensión de app emparejada únicamente con la app).
  • 1C8F.1. Acceder a user defaults para leer/escribir datos solo dentro de apps, extensiones de app y App Clips que son miembros del mismo App Group.
  • C56D.1. Envoltorios de SDKs de terceros que acceden a APIs de user defaults solo cuando la app llama al envoltorio. Solo para SDKs.
  • AC6B.1. Acceder a user defaults para recuperar configuraciones administradas de la app establecidas por un administrador MDM/IT, o para almacenar información de retroalimentación para el administrador.

Casi toda app de iOS usa UserDefaults.standard para al menos un fragmento de estado (la última pestaña seleccionada por el usuario, su orden de clasificación preferido, una bandera de función). La razón CA92.1 lo cubre. Las apps que comparten estado entre extensiones de app a través de un grupo de app agregan 1C8F.1. Los autores de SDKs usan C56D.1. Las apps desplegadas a través de un MDM que leen claves establecidas por el administrador (por ejemplo, com.apple.configuration.managed) usan AC6B.1.

El detalle: un SDK de terceros que toca UserDefaults activa el requisito en nombre de la app. El manifiesto del SDK debe declarar la razón. Si el SDK está en la lista de Apple de SDKs que deben enviar un manifiesto de privacidad, la ausencia del manifiesto del SDK bloquea la app.

Dominios de seguimiento: validación en tiempo de ejecución

NSPrivacyTrackingDomains se aplica a través del Informe de privacidad de la app en tiempo de ejecución6. Cuando una app declara NSPrivacyTracking = true, el sistema rastrea cada solicitud de red y empareja el destino con la lista declarada. Los dominios contactados para seguimiento pero no declarados aparecen en las secciones “Ubicaciones frecuentes” y “Otros dominios contactados” del Informe de privacidad de la app.

La validación en tiempo de ejecución crea una estructura de incentivos interesante. Una app que declara NSPrivacyTracking = false (sin seguimiento) pero que se observa contactando dominios de seguimiento conocidos queda marcada en el Informe de privacidad de la app y arriesga quejas de los usuarios. Lo correcto es la declaración honesta.

Para los SDKs, el manifiesto de privacidad del SDK declara su comportamiento de seguimiento. El manifiesto de la app no necesita enumerar los dominios de seguimiento del SDK; el manifiesto del SDK ya lo hace. En el envío, Apple fusiona los manifiestos y verifica la consistencia.

Manifiestos de SDKs: una obligación real

Los SDKs de terceros en dos categorías deben enviar un manifiesto de privacidad5:

  1. SDKs en la lista publicada por Apple de SDKs que requieren manifiestos de privacidad. La lista incluye Firebase Analytics, Google Mobile Ads, Adjust, Segment, AppsFlyer y alrededor de 30 más a partir de iOS 26.
  2. SDKs distribuidos como binarios precompilados (XCFrameworks, bibliotecas estáticas) contra los que la app se vincula.

El envío de una app que vincula un SDK requerido sin el manifiesto del SDK falla con un error de la serie ITMS-91xxx que cubre el manifiesto de privacidad faltante, la firma del manifiesto faltante o la declaración de API faltante en el espacio de nombres del SDK2. La solución es actualizar a una versión del SDK que incluya manifiesto o eliminar el SDK.

Para SDKs propios (tu equipo envía un framework interno usado por tus apps), puedes elegir omitir el manifiesto si el framework no está en la lista de Apple. Lo pragmático es enviar uno de todas formas: las futuras expansiones de la lista de Apple, el trabajo de auditoría futuro y la reutilización futura por terceros se benefician de tener el manifiesto en su lugar.

Errores comunes

Cinco modos de falla recurrentes de los registros de rechazo de App Store:

1. Declaración de UserDefaults olvidada. El rechazo más común. La app usa @AppStorage (que envuelve UserDefaults) en algún lugar inocuo, el manifiesto no lo declara. Solución: toda app que use @AppStorage, UserDefaults o cualquier envoltorio alrededor de ellos necesita NSPrivacyAccessedAPICategoryUserDefaults con CA92.1.

2. Acceso oculto a marcas de tiempo de archivos a través de URLResourceValues. El código que lee fechas de modificación de archivos a través de URL.resourceValues(forKeys: [.contentModificationDateKey]) activa la categoría, aunque el sitio de la llamada no parezca un stat.

3. Expectativas del manifiesto de SDK. Los equipos de la app asumen que el manifiesto del SDK es problema del autor del SDK. Lo es, pero el envío del equipo de la app falla hasta que el SDK envíe uno.

4. NSPrivacyTracking = false a pesar de un SDK de seguimiento vinculado. Vincular Firebase Analytics o Google Mobile Ads con la configuración predeterminada a menudo activa el comportamiento de seguimiento. El manifiesto de la app que declara NSPrivacyTracking = false mientras el manifiesto del SDK declara true produce una contradicción que la fusión marca.

5. Códigos de razón obsoletos. Apple actualiza ocasionalmente los códigos de razón aprobados. Los códigos que eran válidos en 2024 pueden ser reemplazados o ampliados. La solución es volver a verificar la lista publicada actual en cada versión mayor en lugar de copiar manifiestos antiguos hacia adelante.

Herramientas de validación

Tres verificaciones que vale la pena ejecutar antes del envío:

Flujo de trabajo de archivo “Generar informe de privacidad” de Xcode. Después de Product > Archive, el Organizer ofrece una acción “Generar informe de privacidad” que produce un informe agregado a partir de la app y de cada manifiesto de SDK vinculado. El informe es lo que App Store Connect ingiere; ejecutarlo localmente es lo más cercano a un ensayo previo al envío.

Análisis estático sobre APIs con razón requerida. Las herramientas de código abierto escanean un proyecto en busca de los sitios de llamadas de API que activan las cinco categorías. La CLI mantenida por la comunidad stelabouras/privacy-manifest analiza fuentes Swift y binarios xcframework para mostrar códigos de razón declarados y no declarados; crasowas/app_store_required_privacy_manifest_analyser proporciona un escaneo similar. Cualquiera de los dos ofrece una captura útil previa al envío para declaraciones faltantes.

Verificación cruzada con el Informe de privacidad de la app. Ejecuta la app en el modo Informe de privacidad de la app de iOS (Configuración > Privacidad y seguridad > Informe de privacidad de la app). Los dominios que la app contacta aparecen en el informe; verifica de forma cruzada contra las declaraciones de seguimiento del manifiesto.

Qué significa este patrón para las apps de iOS 26+

Tres conclusiones.

  1. Trata el manifiesto de privacidad como un contrato estructurado, no como una casilla de verificación. El manifiesto es el único registro legible por máquina de lo que la app hace con los datos privados. Construirlo una vez e ignorarlo para siempre es el camino hacia un envío rechazado seis meses después, cuando una actualización de un SDK amplíe silenciosamente la superficie requerida del manifiesto.

  2. Audita el acceso a tu UserDefaults y a las marcas de tiempo de archivos en cada versión. Estas son las dos categorías que crecen silenciosamente con el código base. Una vista SwiftUI que use @AppStorage agregada en una refactorización trae NSPrivacyAccessedAPICategoryUserDefaults al alcance; una función de listado de archivos agregada después trae NSPrivacyAccessedAPICategoryFileTimestamp. Vuelve a validar cada vez.

  3. Usa SDKs que envíen sus propios manifiestos. Al evaluar un SDK de terceros, la presencia y calidad de su manifiesto de privacidad es ahora una señal de calidad. Los SDKs sin manifiestos obligan al equipo de la app a luchar contra la cadena de suministro; los SDKs con manifiestos se integran limpiamente en la fusión.

El cluster completo del Ecosistema Apple: App Intents tipados; servidores MCP; la pregunta de enrutamiento; Foundation Models; la distinción entre LLM en tiempo de ejecución y de herramientas; tres superficies; el patrón de fuente única de verdad; Dos servidores MCP; hooks para el desarrollo de Apple; Live Activities; el contrato de tiempo de ejecución de watchOS; internos de SwiftUI; el modelo mental espacial de RealityKit; disciplina de esquema de SwiftData; patrones de Liquid Glass; envío multiplataforma; la matriz de plataformas; framework Vision; Symbol Effects; inferencia con Core ML; API Writing Tools; Swift Testing; sobre lo que me niego a escribir. El hub está en la Serie del Ecosistema Apple. Para un contexto más amplio sobre iOS con agentes de IA, consulta la guía de Desarrollo de Agentes para iOS.

Preguntas frecuentes

¿Cuál es la diferencia entre NSPrivacyTracking y NSPrivacyCollectedDataTypeTracking?

NSPrivacyTracking es el booleano a nivel de app: ¿esta app rastrea a los usuarios (según la definición restringida de Apple) en absoluto? NSPrivacyCollectedDataTypeTracking es por tipo de dato: para un tipo de dato dado que la app recolecta, ¿se usa ese dato para seguimiento? Una app puede recolectar datos sin rastrear (analítica que no vincula entre empresas); el indicador por tipo captura si cada tipo de dato específico contribuye al comportamiento de seguimiento.

¿Necesito un manifiesto de privacidad para una app de TestFlight solo de uso interno?

Sí. La aplicación del manifiesto de privacidad se ejecuta al enviar a App Store Connect, incluyendo las versiones de TestFlight. Una beta interna sin un manifiesto falla la misma verificación ITMS-91053 que un lanzamiento público.

¿Qué sucede si declaro una API con razón requerida sin usarla?

Nada funcional. El manifiesto declara un límite superior sobre la superficie de la API; declarar una categoría no usada es inofensivo. El costo es la deriva de la documentación: los futuros mantenedores pueden asumir que la declaración refleja el código actual, cuando de hecho la llamada se ha eliminado. Lo correcto es declarar lo que la app realmente usa, auditado en cada versión mayor.

¿Hay categorías de API con razón requerida más allá de las cinco originales?

A partir de iOS 26, las cinco categorías originales (marca de tiempo de archivo, tiempo de arranque del sistema, espacio en disco, teclados activos, User Defaults) siguen siendo la lista canónica4. Apple ha agregado códigos de razón aprobados dentro de las categorías con el tiempo, pero no ha ampliado la lista de categorías. Vigila la página de documentación de API con razón requerida de Apple para adiciones.

¿Cómo interactúa el manifiesto de privacidad con App Tracking Transparency?

App Tracking Transparency (ATT) gobierna el aviso de permiso en tiempo de ejecución para el seguimiento entre apps. El manifiesto de privacidad declara la intención de la app de forma estática. Son complementarios: una app que hace seguimiento entre apps declara NSPrivacyTracking = true en el manifiesto y solicita permiso de ATT en tiempo de ejecución. Una app que declara NSPrivacyTracking = false no debería solicitar ATT (la ausencia de seguimiento entre apps significa que el aviso es innecesario).

Referencias


  1. Documentación para desarrolladores de Apple: Archivos de manifiesto de privacidad. La referencia del formato y la línea de tiempo de aplicación del 1 de mayo de 2024. 

  2. Apple Developer: Errores de envío de App Store Connect que cubren ITMS-91053 (declaración de API faltante) y códigos relacionados. 

  3. Documentación para desarrolladores de Apple: Configuración de privacidad de la app. Las cuatro claves de nivel superior (NSPrivacyTracking, NSPrivacyTrackingDomains, NSPrivacyCollectedDataTypes, NSPrivacyAccessedAPITypes) y sus esquemas. 

  4. Documentación para desarrolladores de Apple: Describir el uso de API con razón requerida. Las cinco categorías de API con razón requerida con códigos de razón aprobados. 

  5. Apple Developer: Requisitos de manifiesto de privacidad para SDKs de terceros. La lista de SDKs que deben enviar un manifiesto de privacidad. 

  6. Documentación para desarrolladores de Apple: Privacidad del usuario y uso de datos. La definición restringida de seguimiento y el framework App Tracking Transparency. 

  7. Documentación para desarrolladores de Apple: NSPrivacyAccessedAPICategoryUserDefaults. La categoría que cubre todo acceso a UserDefaults incluyendo envoltorios basados en @AppStorage

Artículos relacionados

SwiftData's Real Cost Is Schema Discipline

SwiftData's API is two macros. The cost is what happens after you ship. Optional fields are the cheap migration; non-opt…

15 min de lectura

Liquid Glass in SwiftUI: Three Patterns From Shipping Return on iOS 26

Apple's Liquid Glass is a one-line SwiftUI API. Three patterns from Return go beyond .glassEffect(): glass on text via C…

19 min de lectura

The Cleanup Layer Is the Real AI Agent Market

Charlie Labs pivoted from building agents to cleaning up after them. The AI agent market is moving from generation to pr…

15 min de lectura