← Todos los articulos

Única fuente de verdad: SwiftData, MCP, iCloud

Get Bananas tiene tres llamadores que pueden escribir en la misma lista de compras. Una persona tocando filas en la app de iOS. Apple Intelligence enrutando una solicitud de Siri a través de un AppIntent. Una sesión de Claude Code llamando a una herramienta MCP por stdio. La lista es una sola cosa canónica en la cabeza del usuario; la pregunta es dónde vive en almacenamiento y qué llamador gana cuando hay desacuerdo.

La publicación de síntesis nombró las tres superficies de una app de iOS: persona, Apple Intelligence, agente. Cada superficie necesita leer y escribir el mismo estado del dominio. Esa demanda es la que produce el error arquitectónico que se envía en demasiadas apps: cada superficie obtiene su propio almacén, las superficies se desincronizan y el usuario ve tres versiones diferentes de su lista dependiendo de cuál tocó por última vez. El patrón que sobrevive es una única fuente de verdad con rutas de sincronización explícitas entre las superficies y el sustrato.

La publicación nombra las opciones de sustrato, las reglas de resolución de conflictos que cada una impone y la arquitectura que se sostiene cuando las tres clases de llamadores pueden escribir. El recorrido usa la disposición real de Get Bananas: SwiftData para el estado dentro de la app, un archivo JSON en iCloud Drive para la sincronización entre procesos, un servidor MCP leyendo y escribiendo el mismo archivo desde fuera del sandbox de iOS.1

TL;DR

  • Tres sustratos componen: SwiftData (en proceso, rápido, tipado por esquema), iCloud Drive (entre procesos, basado en archivos, sincronizable), NSUbiquitousKeyValueStore (entre dispositivos, clave-valor, solo carga útil pequeña).
  • Elige qué sustrato es la fuente de verdad por dominio. La resolución de conflictos es una consecuencia forzada de la elección, no un problema separado.
  • Las tres superficies (persona, Apple Intelligence, agente) interactúan con el sustrato a través de la capa de dominio. La capa de dominio es donde vive la política de resolución de conflictos.
  • Una marca de tiempo lastModified en cada entidad mutable es la primitiva barata de resolución de conflictos; “el último escritor gana” es la política barata. Las apps que necesitan garantías más fuertes pagan por ellas con lógica de fusión explícita.
  • Un servidor MCP fuera del proceso de la app no puede leer SwiftData. El puente es una capa de serialización (archivo JSON en iCloud Drive, contenedor de App Group, etc.) con la que tanto el lector de SwiftData dentro de la app como el servidor MCP fuera del proceso pueden hablar.

Los tres sustratos

Apple les da a las apps de iOS enviadas tres sustratos de persistencia nativos que aparecen en patrones entre procesos y entre dispositivos. Cada uno tiene una forma específica; mezclarlos sin un plan produce el problema de desincronización.

SwiftData. Almacenamiento persistente en proceso respaldado por Core Data.2 Rápido, tipado por esquema, consultable a través de @Query, integrado con el sistema de observación de SwiftUI. El almacén es propiedad del proceso de la app. Las extensiones de la app (widgets, intents, extensiones de compartir) pueden compartir un contenedor de SwiftData a través de un App Group con configuración explícita; un proceso MCP externo arbitrario que se ejecuta en la máquina de un desarrollador fuera del contexto de firma de la app no puede alcanzar el contenedor de SwiftData de forma segura. Las filas son direccionables a través de PersistentIdentifier (en proceso) o claves naturales @Attribute(.unique) (entre procesos, entre dispositivos). Las migraciones son declarativas a través de VersionedSchema y MigrationPlan (cubierto en El verdadero costo de SwiftData es la disciplina de esquema).

iCloud Drive. Sincronización entre dispositivos basada en archivos, expuesta a través de URLs de FileManager en el contenedor de iCloud del usuario.3 Los archivos aparecen en cada dispositivo en el que el usuario ha iniciado sesión. La resolución de conflictos es a nivel de archivo: iCloud usa NSFileVersion para rastrear ediciones concurrentes, y la app lee el registro de conflictos para decidir qué conservar. Los archivos en iCloud Drive son direccionables desde fuera del proceso de la app de iOS: un servidor MCP en Mac puede abrir el mismo archivo JSON que lee la app de iOS. El sustrato es lo que hace que la integración MCP de Get Bananas funcione.

NSUbiquitousKeyValueStore. Almacenamiento clave-valor entre dispositivos. Los límites públicos actuales de Apple son 1MB total por app, 1MB por valor, 1024 claves, 128 caracteres UTF-16 por clave, con tasas de escritura limitadas.4 La resolución de conflictos está integrada: el sistema serializa las escrituras y notifica a todos los dispositivos en el cambio. Apropiado para estado pequeño y de baja frecuencia (configuración, última pestaña seleccionada, un contador entero); inapropiado para datos de alta frecuencia de escritura o cargas de trabajo donde el límite se convierte en el cuello de botella. Return lo usa para el estado del temporizador entre dispositivos (el usuario inicia un temporizador en el iPhone, lo ve en el Apple Watch); cubierto en Cinco plataformas de Apple, tres archivos compartidos.

El cuarto sustrato, CloudKit, es la elección que parece obvia y que las apps del clúster han rechazado explícitamente para la integración MCP entre procesos. CloudKit ofrece sincronización fuerte entre dispositivos con registros conscientes de conflictos, y Apple sí envía CloudKit JS y CloudKit Web Services para que entornos no-Apple hablen con bases de datos públicas y privadas de CloudKit. La compensación honesta es el costo de integración, no la imposibilidad: un servidor MCP en Node.js que alcance una base de datos privada de CloudKit tiene que cablear la autenticación de CloudKit Web Services, las definiciones de esquema y la firma de solicitudes, lo cual es trabajo de ingeniería material comparado con “abre un archivo JSON”. Get Bananas eligió iCloud Drive más un archivo JSON porque el servidor MCP es un proceso de Node.js que necesita leer y escribir los mismos datos que ve la app de iOS, y la E/S de archivos ordinaria es el camino de menor resistencia.1

La decisión: qué sustrato sostiene la verdad

La pregunta no es qué sustrato usar. La pregunta es qué sustrato es la fuente de verdad para qué dominio. Los demás sustratos lo cachean, lo reflejan o se quitan del camino.

La matriz de decisión que sobrevive a producción para las apps del clúster:

Forma del dominio Fuente de verdad Por qué
Configuración, preferencias, banderas simples NSUbiquitousKeyValueStore La sincronización entre dispositivos es automática; las colisiones se serializan; la carga útil pequeña encaja
Estado transitorio por dispositivo UserDefaults (sin sincronización) Local del dispositivo; no debe sobrevivir a una instalación nueva en un dispositivo diferente
Colección consultable en proceso SwiftData @Query rápido, observación de SwiftUI, tipado por esquema; solo en proceso
Colección en proceso que debe alcanzar procesos externos Archivo JSON en iCloud Drive (exportar a disco) Tanto el lector de SwiftData de iOS como el servidor MCP externo pueden leer el archivo
Contenido grande por usuario (fotos, audio, documentos) iCloud Drive (por archivo) El iCloud del usuario es el almacén natural; CloudKit puede agregarse encima para una sincronización más rica
Estado a nivel de sesión entre dispositivos (temporizador corriendo en iPhone, visible en Watch) NSUbiquitousKeyValueStore Encaja en el sobre de tamaño; necesita la semántica de push entre dispositivos

La decisión configura la política de resolución de conflictos. Para el puente app-local-más-MCP-externo, SwiftData no tiene resolución de conflictos inherente entre procesos; si dos llamadores escriben en la misma fila, el último try context.save() gana. SwiftData respaldado por CloudKit y usando historial persistente puede llevar una semántica más rica entre dispositivos, pero esa superficie es del lado de iOS y no ayuda al caso de Node.js MCP externo. iCloud Drive expone los conflictos como entradas de NSFileVersion; la app tiene que recorrerlas y elegir un ganador. NSUbiquitousKeyValueStore tiene resolución de conflictos integrada al nivel del valor.

La arquitectura de Get Bananas

La disposición real de Get Bananas:

                     ┌────────────────────────────────────┐
                     │           User's mental model       │
                     │         "my shopping list"          │
                     └─────────────────┬──────────────────┘
                                       │
                          ┌────────────┴───────────┐
                          │                        │
                  ┌───────▼────────┐      ┌───────▼─────────┐
                  │   iOS app      │      │  MCP server      │
                  │  (Get Bananas) │      │  (Node.js)       │
                  └───────┬────────┘      └───────┬─────────┘
                          │                        │
              ┌───────────┴────────┐               │
              │                    │               │
       ┌──────▼──────┐    ┌────────▼──────────┐   │
       │  SwiftData   │    │  iCloud Drive     │◀──┘
       │ (in-process) │◀──▶│  shopping_list.   │
       │              │    │       json        │
       └──────────────┘    └───────────────────┘

  In-app reads/writes flow through SwiftData.
  Cross-process reads/writes flow through the JSON file.
  An iCloud sync layer (iCloudBackupManager) reconciles the two.

La arquitectura tiene tres reglas.

SwiftData es la fuente de verdad para las consultas en proceso. La app de iOS lee desde SwiftData para cada renderizado de UI, cada lista respaldada por @Query, cada búsqueda. Las escrituras pasan primero por SwiftData; el contexto del modelo guarda; SwiftUI vuelve a renderizar.

El archivo JSON es la fuente de verdad para el estado entre procesos. Cada vez que la app de iOS guarda en SwiftData, un gestor de respaldo de iCloud exporta el estado actual a un archivo JSON en el contenedor de iCloud Drive del usuario. Cada vez que el servidor MCP escribe, escribe en el mismo archivo JSON. El archivo es el puente.

Una pasada de sincronización se ejecuta al lanzar la app de iOS y después de cada escritura entre procesos. La lógica de sincronización en producción hoy (SyncManager.applyExport) trata el respaldo JSON como autoritativo en cada pasada: lee el archivo JSON, hace coincidir cada fila con SwiftData por UUID, sobrescribe las filas existentes con los valores del respaldo, agrega las filas que el respaldo tiene pero SwiftData no, y elimina las filas que SwiftData tiene pero el respaldo no (con una protección contra corrupción para evitar que un archivo de respaldo vacío borre la base de datos local). La política es el respaldo gana en el momento de sincronización, no por fila el último-escritor-gana por marca de tiempo. Combinado con la app de iOS reexportando después de cada guardado, la convergencia en estado estable es rápida en la práctica: cualquier proceso que haya escrito más recientemente produjo el JSON que la siguiente sincronización lee.

La arquitectura intercambia complejidad por alcance entre procesos. Una app puramente de SwiftData no necesita nada de esto; una app sin servidor MCP no necesita el puente JSON; una app sin sincronización entre dispositivos no necesita el reconciliador. Get Bananas necesita los tres porque las tres clases de llamadores (persona vía iOS, Apple Intelligence vía App Intents en iOS, agente vía MCP desde la máquina de un desarrollador Mac) tocan la misma lista de compras.

La ruta de actualización: el último escritor gana por fila

La política enviada de “el respaldo gana en el momento de sincronización” es barata y funciona para el caso de un solo usuario, un solo escritor activo a la vez. Tiene problemas cuando tanto la app de iOS como el servidor MCP escriben en el archivo JSON en sucesión cercana: el proceso que haya escrito más recientemente sobrescribe los cambios del otro, incluso para filas que en realidad no tenían conflicto. La mitigación hoy es que la app de iOS reexporta después de cada guardado de SwiftData, lo que mantiene el archivo JSON aproximadamente alineado con el estado más reciente dentro de la app. El estado estable está bien; el caso genuinamente concurrente puede perder trabajo.

La actualización más barata es el último-escritor-gana por fila con clave en una columna lastModified: Date?. El modelo ShoppingItem ya tiene el campo por seguridad de migración (cubierto en El verdadero costo de SwiftData es la disciplina de esquema), pero la exportación JSON y el servidor MCP actualmente no lo serializan ni lo respetan. Hilar lastModified a través de la exportación y a través de applyExport cambiaría la política de fusión de “el respaldo gana” a “la fila más nueva gana”:

  • Ambos lados tienen un valor, uno es más reciente. El más reciente gana. La fila del otro lado se actualiza.
  • Ambos lados tienen un valor, empatan. Desempate por clave primaria, o por superficie (la app de iOS gana los empates para favorecer la interacción más reciente del usuario dentro de la app).
  • Un lado tiene un valor, el otro no. El lado con el valor gana.
  • Ningún lado tiene un valor. Ambas filas son datos de la era pre-lastModified. El reconciliador estampa Date() para la próxima vez.

La política es barata, fácil de razonar y está equivocada en aproximadamente el 1% de los casos (ediciones concurrentes a campos diferentes de la misma fila). Para una lista de compras, ese 1% no importa; para un editor de documentos, importa absolutamente. Las apps que necesitan garantías más fuertes superponen fusión a nivel de campo, CRDTs o transformaciones operacionales sobre esta base; Get Bananas aún no ha necesitado esa complejidad, por eso el LWW por fila está en la hoja de ruta y la fusión más rica no.

Las tres clases de llamadores y el sustrato

Mapeando las clases de llamadores de Tres superficies a las decisiones de sustrato:

La superficie humana escribe a través de SwiftData. Un usuario tocando una casilla en la app de iOS dispara a través de la capa de SwiftUI a una función de dominio que muta la fila de SwiftData, estampa lastModified = Date() en el modelo y guarda el contexto del modelo. La exportación a iCloud escribe el estado actual en el archivo JSON. El servidor MCP recoge el nuevo estado en su próxima lectura.

La superficie de Apple Intelligence escribe a través de SwiftData. Un AppIntent invocado a través de Siri se ejecuta en el proceso de la app de iOS y alcanza la misma función de dominio que usa la superficie humana. El estado de SwiftData muta, el lastModified del modelo se actualiza y la exportación JSON captura el nuevo estado.

La superficie del agente escribe a través del archivo JSON. Una llamada de herramienta MCP desde una sesión de Claude Code en una Mac muta el archivo JSON directamente (con bloqueo de archivos para manejar escrituras concurrentes desde la app de iOS). La próxima vez que la app de iOS se lance o sincronice, SyncManager.applyExport lee el archivo, recorre los elementos por UUID, actualiza las filas que existen en ambos lados con los valores del respaldo, agrega las filas que el respaldo tiene y elimina las filas que el respaldo omite (con la protección de respaldo vacío). La política enviada es el respaldo gana en el momento de sincronización; la ruta de actualización agrega lastModified al JSON para que la política pueda cambiar a la fila más nueva gana.

La asimetría es real e intencional. Las superficies humana y de Apple Intelligence se ejecutan dentro del proceso de la app de iOS y usan SwiftData de forma nativa. La superficie del agente se ejecuta fuera del proceso de la app de iOS y usa el archivo JSON porque ese es el sustrato que puede alcanzar. El reconciliador es lo que mantiene unidas las dos mitades.

Cuándo este patrón es la respuesta equivocada

Algunos casos donde el patrón puente-JSON es incorrecto.

Datos de alta frecuencia de escritura. Un editor de documentos en vivo con muchas ediciones por segundo no puede pagar el costo de serializar toda la colección a un archivo JSON en cada escritura. La respuesta correcta son las transformaciones operacionales o CRDTs contra un backend real.

Requisitos de consistencia fuerte. Un libro mayor de transacciones financieras no puede tolerar el último-escritor-gana en el archivo JSON. La respuesta correcta es CloudKit (o una base de datos del lado del servidor) con semántica explícita de transacciones.

Colaboración multiusuario donde los usuarios ven las ediciones de los demás en tiempo real. La sincronización de iCloud Drive es eventual, no en tiempo real. El usuario que cierra la app en un dispositivo y la abre en otro ve el estado que se sincronizó; el usuario que ve el cursor de otro usuario moviéndose por un documento no. La respuesta correcta es un framework de colaboración en tiempo real (yjs, automerge o una capa WebSocket personalizada).

Casos donde el agente y el usuario son identidades diferentes. El patrón de Get Bananas asume que el agente (el llamador MCP) y el usuario humano (el usuario de la app de iOS) son la misma persona, solo operando entre procesos. Si el agente está actuando en nombre de una identidad diferente (una lista compartida, un administrador, un bot automatizado), el archivo JSON en el iCloud Drive del usuario es el sustrato equivocado; se requiere persistencia multiusuario con autenticación explícita.

El patrón encaja en el caso de un solo usuario, eventualmente consistente, entre procesos. La mayoría de las apps con integraciones MCP son exactamente ese caso; algunas no.

Qué construiría diferente

Tres patrones que las apps del clúster han enviado o desearían haber tenido.

Haz que la serialización JSON sea explícita, no implícita. La primera versión de Get Bananas exportaba cada escritura de SwiftData a JSON en un hook de guardado. La segunda versión hizo de la exportación un paso explícito que la app llama cuando el estado se ha estabilizado. El cambio redujo las escrituras redundantes y dejó claro cuándo se había publicado el estado entre procesos. Un hook implícito guardar-en-cada-mutación produce demasiada E/S para cualquier colección no trivial.

Versiona el esquema del archivo JSON. El archivo JSON tiene su propio esquema independiente del VersionedSchema de SwiftData. Cuando el esquema de SwiftData cambia (digamos, agregando un campo), la serialización JSON tiene que seguir. La solución barata es poner un campo schemaVersion: Int en la parte superior del JSON; el reconciliador lo lee y aplica la interpretación correcta. Sin versionado, una app de iOS v2 leyendo un archivo JSON v1 escrito por un servidor MCP antiguo sufre corrupción silenciosa de datos.

Bloquea con archivos el JSON, no asumas coordinación. La app de iOS y el servidor MCP ambos escriben en el archivo JSON. Sin un NSFileCoordinator (en proceso, lado iOS) y un bloqueo de archivos (fuera de proceso, en la máquina del desarrollador), las escrituras concurrentes pueden producir un archivo corrupto. El servidor MCP de Get Bananas usa un bloqueo de archivos estilo flock en el JSON; la app de iOS usa NSFileCoordinator para sus escrituras; el archivo rara vez está disputado en la práctica, pero el cinturón de seguridad es barato.

Qué significa el patrón para apps que se envían en iOS 26+

Tres conclusiones.

  1. Elige una fuente de verdad por dominio. Los demás sustratos cachean, reflejan o se quitan del camino. SwiftData para consultas en proceso, JSON en iCloud Drive para puentes entre procesos, NSUbiquitousKeyValueStore para estado pequeño entre dispositivos. La resolución de conflictos es una consecuencia derivada de la elección.

  2. lastModified más el último-escritor-gana es el caso base barato. La mayoría de las apps no necesitan garantías más fuertes. El 1% de los casos que necesitan fusión a nivel de campo o CRDTs es caro de agregar; no pagues el costo hasta que la forma de los datos lo demande.

  3. El reconciliador es la pieza estructural. Cuando SwiftData y el archivo JSON no están de acuerdo, el reconciliador decide. El reconciliador se ejecuta al lanzar la app, después de las escrituras entre procesos y después de los eventos de sincronización de iCloud. Las reglas son simples; la disciplina es realmente ejecutarlo.

El clúster completo de Apple Ecosystem: App Intents tipados para la superficie de Apple Intelligence; servidores MCP para la superficie del agente; la pregunta de enrutamiento entre ellos; Foundation Models para funciones LLM en el dispositivo dentro de la app; la distinción entre LLM en runtime y en tooling; la síntesis de las tres superficies de una app de iOS; Live Activities para la máquina de estado de la pantalla bloqueada de iOS; el contrato del runtime de watchOS en Apple Watch; los internals de SwiftUI para el sustrato de la superficie humana; el modelo mental espacial de RealityKit para escenas de visionOS; disciplina de esquema en SwiftData para persistencia; patrones de Liquid Glass para la capa visual; envío multiplataforma para alcance entre dispositivos. El hub está en la Serie Apple Ecosystem. Para contexto más amplio de iOS-con-agentes-de-IA, consulta la guía de desarrollo de agentes en iOS.

Preguntas frecuentes

¿Por qué no usar CloudKit para sincronización entre procesos?

CloudKit ofrece sincronización fuerte entre dispositivos con registros conscientes de conflictos, y CloudKit JS / CloudKit Web Services de Apple sí permiten que stacks no-Apple alcancen una base de datos privada de CloudKit. La restricción es el costo de integración: un servidor MCP en Node.js usando CloudKit tiene que manejar la autenticación de CloudKit (claves servidor-a-servidor o tokens a nivel de usuario), las declaraciones de esquema y las solicitudes firmadas. iCloud Drive más un archivo JSON es E/S de archivos ordinaria, que es el traductor universal. CloudKit es la elección correcta cuando el equipo está dispuesto a pagar el costo de integración y quiere la sincronización más fuerte y la semántica de conflictos de CloudKit; el puente JSON es la elección correcta cuando “abre un archivo” es suficiente para la forma de los datos.

¿Cómo manejas conflictos cuando dos llamadores escriben al mismo tiempo?

La política enviada de Get Bananas es “el respaldo gana en el momento de sincronización”: SyncManager.applyExport recorre los elementos por UUID y sobrescribe las filas locales desde el respaldo, con una protección contra un respaldo vacío que borre buenos datos locales. La ruta de actualización es el último-escritor-gana por fila con clave en lastModified, que el modelo ya lleva pero que aún no se serializa a través del puente JSON. Agregarlo resolvería el ~99% de los conflictos donde un lado es genuinamente más nuevo; el 1% restante (ediciones concurrentes a campos diferentes de la misma fila) es lo suficientemente raro para que las apps hasta ahora omitan la fusión a nivel de campo o CRDTs. Las apps con requisitos de consistencia más fuertes superponen fusión más rica encima.

¿Dónde encaja SwiftData si iCloud Drive es la fuente de verdad para el estado entre procesos?

SwiftData es la fuente de verdad para las consultas en proceso. La app de iOS lee SwiftData para cada renderizado de UI, cada @Query, cada búsqueda. SwiftData es rápido, tipado por esquema e integrado con el sistema de observación de SwiftUI. Cuando la app de iOS escribe, el cambio va primero a SwiftData, luego se exporta al archivo JSON. El archivo JSON es la fuente de verdad para las lecturas entre procesos (la vista del servidor MCP); SwiftData es la fuente de verdad para las lecturas en proceso (la vista de la UI de iOS). Se mantienen alineados a través del reconciliador.

¿Qué pasa con NSUbiquitousKeyValueStore para la lista de compras en sí?

NSUbiquitousKeyValueStore está limitado a 1MB total por app y 1MB por valor con escrituras limitadas, y serializa en un diccionario de 1024 claves. Una lista de compras con cientos de elementos más historial puede caber por conteo de bytes, pero escribir cambios por elemento a través del límite es la forma equivocada; las actualizaciones masivas de colecciones compiten por el presupuesto de tasa contra todo lo demás que la app almacena. El sustrato correcto para colecciones es SwiftData (en proceso) o iCloud Drive (entre procesos). Reserva NSUbiquitousKeyValueStore para estado clave-valor pequeño y de baja frecuencia: configuración, la última pestaña seleccionada, un contador, una anulación de bandera de característica.

¿Cómo sé qué sustrato elegir para un nuevo dominio en mi app?

Tres preguntas en orden. Primera: ¿algo fuera del proceso de la app de iOS necesita leer o escribir este dominio? Si sí, necesitas iCloud Drive (basado en archivos, E/S de archivos ordinaria) o CloudKit (a través de los frameworks de Apple o CloudKit Web Services desde stacks no-Apple) o un servidor que controles. Si no, SwiftData es el predeterminado. Segunda: ¿esto necesita sincronizarse entre los dispositivos del usuario? Si sí, el sustrato tiene que soportarlo (iCloud Drive lo hace, SwiftData no a menos que esté emparejado con sincronización de iCloud). Tercera: ¿qué tan grande es la carga útil y con qué frecuencia cambia? Pequeño + baja frecuencia vive en NSUbiquitousKeyValueStore; todo lo demás necesita una capa de persistencia real.

Referencias


  1. Análisis del autor en Dos ecosistemas de agentes, una lista de compras, 29 de abril de 2026, y la capa de sincronización JSON en iCloud Drive del proyecto Get Bananas en Banana List/iCloudBackupManager.swift. La arquitectura empareja SwiftData con un archivo JSON en el contenedor de iCloud Drive del usuario que un servidor MCP externo lee y escribe. 

  2. Apple Developer, “SwiftData” y “Adding and editing persistent data in your app”. El macro @Model, las restricciones @Attribute y la relación con el NSManagedObjectModel de Core Data. El análisis del autor en El verdadero costo de SwiftData es la disciplina de esquema cubre VersionedSchema y MigrationPlan para una evolución segura del esquema. 

  3. Apple Developer, “Synchronizing documents in the iCloud environment”. Sincronización entre dispositivos basada en archivos, resolución de conflictos a través de NSFileVersion y la API NSFileCoordinator para escrituras seguras en proceso contra archivos compartidos. 

  4. Apple Developer, “NSUbiquitousKeyValueStore”. Almacenamiento clave-valor entre dispositivos. Límites actuales de Apple: 1MB total por app, 1MB por valor, 1024 claves, 128 caracteres UTF-16 por clave, tasa de escritura limitada. El análisis del autor en Cinco plataformas de Apple, tres archivos compartidos cubre el patrón de temporizador entre dispositivos que Return envía usando esta API. 

Artículos relacionados

Servidor MCP junto a una app de iOS: dos ecosistemas de agentes, una sola lista

Get Bananas funciona en iOS, macOS, watchOS y visionOS. También vive dentro de Claude Desktop como un servidor MCP. El p…

18 min de lectura

App Intents vs MCP: la cuestión del enrutamiento

Dos protocolos, una sola app. App Intents expone tu app a Apple Intelligence. MCP expone el mismo dominio a Claude, Chat…

15 min de lectura

Tu agente tiene un intermediario que no verificaste

Investigadores probaron 28 routers de API de LLM pagos. 17 tocaron credenciales canary de AWS. Uno drenó ETH de una clav…

14 min de lectura