Saltar al contenido
megapromotingVamos a hablar

Experiencia · Aplicaciones móviles

Aplicaciones para teléfono, construidas de modo que la lógica pueda verificarse sin teléfono.

Construimos aplicaciones nativas iOS en Swift, con sensores y HealthKit, y aplicaciones con un solo código para iOS, Android y web cuando el proyecto no requiere sensores. El núcleo de lógica se prueba aparte de la pantalla.

Ya construidoSunt trei implementări proprii, nu una. Un depozit cu cinci ținte de aplicație (patru iOS și una macOS) definite în `project.yml`, ale cărui teste de logică le-am rulat azi: 160 din 160 trec. O a doua aplicație iOS, în alt proiect, cu 40 de fișiere Swift și HealthKit. Și o a treia direcție, cu un singur cod pentru iOS, Android și web, a cărei variantă web răspunde astăzi. Rezerva care schimbă răspunsul la întrebarea pe care o pune orice cumpărător înainte de toate: niciuna dintre aplicațiile noastre nu este publicată în App Store sau Google Play. Motivul e unul singur și are nume — `DEVELOPMENT_TEAM` este gol în configurația de proiect, adică lipsește identificatorul de echipă din Apple Developer Program. Mașina are o identitate de semnare validă, suficientă pentru instalare pe dispozitiv propriu, insuficientă pentru distribuție în magazin. E o problemă de cont, nu de cod, dar rămâne o problemă și o scriem aici, nu la subsol.

Una aplicación móvil tiene dos partes que se rompen de forma diferente. La parte que lee los sensores y calcula algo — un ángulo, una puntuación, un estado — y la parte que dibuja pantallas. Las mantenemos separadas, y no por motivos estéticos: en nuestro repositorio principal de iOS, los archivos del núcleo no importan la interfaz, así que pueden compilarse directamente con `swiftc` en Mac y ejecutarse como un programa normal, sin simulador y sin teléfono. La suite tiene 160 comprobaciones agrupadas en 16 etapas; la ejecutamos hoy y pasa íntegramente. Esa es la razón por la que podemos decir qué hace exactamente un algoritmo, en lugar de decir que "funciona bien".

En iOS trabajamos en Swift 6, con objetivo mínimo iOS 17. Ese mismo repositorio define cinco aplicaciones como objetivos separados: cuatro para iPhone y una para macOS, y la de macOS reutiliza quince archivos del núcleo de iOS, sin copiar. Los sensores se leen en la fuente: la interfaz de Apple para los sensores de los auriculares expone la orientación de la cabeza, y la aplicación compara el ángulo actual con una posición que el usuario calibra al inicio de la sesión. Los umbrales no son «ajustes internos»: por debajo de 7° está recto, entre 7° y 13° está deslizándose, por encima de 13° sostenido durante tres segundos activa la alerta, y el suavizado usa una media exponencial con el coeficiente 0,15. Los cuatro valores están en cuatro líneas consecutivas de código y pueden mostrarse.

Cuando el proyecto no necesita sensores, no recomendamos nativo. La tercera dirección del portafolio es un solo código que se compila para iPhone, Android y navegador — React Native con Expo — y la versión web está publicada y responde hoy. La diferencia práctica para el cliente: un cuestionario, una calculadora o un panel de control no justifican dos equipos y dos repositorios; una aplicación que escucha un sensor a veinte muestras por segundo, sí.

Lo que aún no podemos. Ninguna de nuestras aplicaciones está en App Store ni en Google Play. No porque no compile — compila, se instala en el simulador y pasa las pruebas — sino porque en la configuración del proyecto el identificador de equipo de Apple está vacío, es decir, no existe una inscripción en el Apple Developer Program vinculada a estos builds. En Mac existe una identidad de firma válida, de tipo desarrollo, que basta para la instalación en el propio dispositivo y no basta para la tienda. Para un proyecto de cliente, la cuenta de desarrollador se abre a nombre de la empresa del cliente y queda suya — esa es la conversación que hay que tener al inicio, no al final.

Qué incluye

El trabajo, por componentes

Leemos el sensor en la fuente, no mediante una biblioteca intermedia

En iOS usamos directamente las interfaces de Apple: `CMHeadphoneMotionManager` para la orientación de la cabeza en los auriculares, con delegado para conexión y desconexión, y verificación explícita del estado de autorización antes de iniciar el flujo. Si el sensor no está disponible, el estado pasa a `waiting`, no a un error silencioso.

El núcleo de lógica no sabe que existe una pantalla

Los archivos de análisis, calibración, historial y políticas son Swift simple. Se compilan con `swiftc` junto con el archivo de pruebas y se ejecutan como binario de línea de comandos. El resultado de hoy: 160 verificaciones, 16 etapas de 10, todas pasadas. Una prueba que corre en dos segundos en Mac se ejecuta con cada cambio; una que requiere simulador, no.

La interfaz se construye sobre el núcleo, en iOS y en macOS al mismo tiempo

SwiftUI para ambos. El objetivo de macOS del mismo repositorio incluye quince archivos del núcleo de iOS como fuentes compartidas, no como archivos copiados, así que una corrección en el algoritmo llega simultáneamente a ambas aplicaciones.

Un solo código para iOS, Android y web, cuando esa es la elección correcta

Expo sobre React Native, con `react-native-web` para la versión de navegador, fuentes cargadas desde el paquete e iconos de aplicación separados para Android, incluida la variante monocroma que exige el sistema. La misma aplicación funciona en el teléfono y en la página, desde un solo repositorio.

Datos de salud: una política declarada para cada tipo de dato

No “leemos HealthKit”, sino una tabla en el código: once tipos de datos (ángulos posturales, movimiento bruto de los auriculares, pulso y variabilidad, sueño, marcha, exposición al audio, sesiones guiadas y otros) y cinco regímenes posibles (solo local, lectura desde HealthKit, escritura de entrenamiento, escritura de sesión de relajación, escritura de recorrido). Cada tipo recibe explícitamente uno de los regímenes. La segunda aplicación iOS del portafolio, de un proyecto privado, usa el mismo enfoque en 40 archivos Swift.

Los archivos de privacidad requeridos por Apple, presentes desde el principio

Cuatro objetivos tienen `PrivacyInfo.xcprivacy` incluido como recurso de compilación, no añadido a toda prisa tras el primer rechazo. Las descripciones de uso para movimiento, cámara, micrófono, HealthKit y notificaciones están escritas en rumano, en la configuración del proyecto, no generadas automáticamente.

Lo que sale del teléfono: en el caso de la aplicación iOS de referencia, nada

La búsqueda de `URLSession` en las fuentes del objetivo iOS devuelve cero resultados. El historial se escribe en el dispositivo, mediante `FileManager` y `UserDefaults`, con opción de borrar el archivo. El único código de red del repositorio está en una función de la aplicación de macOS, en un archivo separado. Cuando una aplicación no necesita servidor, no se lo ponemos.

El recorrido de inicio, probado como estado, no como pantalla

El onboarding tiene 24 pasos con identificadores únicos y ordenados, y algunos pasos requieren una confirmación explícita (los límites del sensor, el funcionamiento en primer plano, la confidencialidad, la preparación) sin la cual el botón de continuar sigue bloqueado. El estado se codifica y se reanuda. Diez de las 160 pruebas verifican exactamente eso.

Firma y distribución, dichas desde el principio

Verificamos qué cuenta de desarrollador existe, a nombre de qué empresa, quién la administra y qué falta para que el build pueda firmarse para la tienda. Es una lista corta y aburrida, pero es la diferencia entre una aplicación que funciona en nuestro teléfono y una que llega a los usuarios.

Qué aspecto tiene

El recorrido, paso a paso.

01

Decidimos nativo o código compartido, en función de los sensores

La pregunta no es de gusto, sino de hardware: ¿la aplicación necesita movimiento, salud, Bluetooth, cámara en tiempo real, segundo plano? Si sí, nativo. Si se trata de formularios, cálculos, listas y un panel de control, un solo código para iOS, Android y web hace el mismo trabajo con la mitad de mantenimiento. Entregamos la decisión por escrito, con el motivo.

02

Construimos el núcleo antes que las pantallas y lo cubrimos con pruebas que se ejecutan sin teléfono

El algoritmo, los umbrales, los estados y la persistencia. Las pruebas se compilan directamente en Mac y se ejecutan en unos segundos. Entregamos la suite y su resultado, no una promesa de calidad.

03

Ponemos la interfaz sobre el núcleo y ejecutamos en simulador y en dispositivo

SwiftUI en iOS y macOS, o React Native cuando hemos elegido el código compartido. Verificamos el recorrido de inicio, los permisos y el comportamiento cuando el sensor falta o se desconecta en mitad de la sesión —el caso que suele fallar en la práctica.

04

Preparamos la distribución, con la cuenta del cliente

Identificador de paquete, versión, iconos, archivo de privacidad, descripciones de permisos, identificador de equipo de Apple Developer Program. Aquí se bloquean los proyectos que no discutieron la cuenta al principio, incluidos los nuestros, que es exactamente el motivo por el que ponemos este paso por escrito.

Ce vede utilizatorulAplicațiaRețea și securitateGăzduire și dateFIECARE STRAT, ALES ȘI EXPLICAT
Patru straturi, de jos în sus: senzorii platformei (mișcare din căști, HealthKit, notificări); nucleul de logică în Swift simplu, care nu importă interfața și de aceea poate fi rulat pe Mac fără telefon; interfața SwiftUI, aceeași pentru iPhone și macOS; și stratul de distribuție — fișier de confidențialitate, permisiuni declarate, semnare. Ultimul strat e singurul pe care nu l-am parcurs până la capăt, și de aceea e desenat deschis.

Los datos

Qué tocamos, dónde están y cuánto se quedan

Las preguntas que hace cualquiera que tenga un delegado de protección de datos — hechas aquí antes de que las haga él.

Dónde están los datos cuando la aplicación no tiene servidor
En el dispositivo. El historial postural se serializa en un archivo propio mediante `FileManager`, y las preferencias en `UserDefaults`, con claves prefijadas por aplicación. Existe un comando para borrar el archivo del historial. Nada sale hacia un servidor por la simple razón de que la aplicación no contiene código de red.
Los datos de salud se leen solo con consentimiento, y solo los declarados
HealthKit pide el consentimiento del usuario a nivel de tipo de dato, y la aplicación declara en la configuración por qué los solicita. La política en el código separa explícitamente lo que se lee de lo que se escribe de vuelta en Salud. No se hace diagnóstico y no se transmite nada hacia nosotros.
Lo que Apple te pide declarar, hagas lo que hagas con los datos
El archivo de privacidad de la aplicación y las descripciones de uso para cada permiso (movimiento, cámara, micrófono, salud, notificaciones). Son condición de aceptación en la tienda, no una opción, y se redactan en el idioma en que habla el usuario.
Cuánto se conserva
Lo que decida el usuario, cuando los datos están en el teléfono: la desinstalación de la aplicación se los lleva, y el borrado desde la aplicación es una operación explícita. Cuando un proyecto sí tiene servidor, la retención se escribe en el contrato antes de la primera línea de código, porque determina qué se puede y qué no se puede construir.
La cuenta de desarrollador y las claves de firma
Siguen siendo del cliente, en la empresa del cliente. Nosotros trabajamos con acceso delegado. El motivo es práctico, no de principio: una aplicación publicada en la cuenta del proveedor se vuelve imposible de mover el día en que el proveedor cambia.

Un caso

Una aplicación de iPhone que mide una sola cosa, y la mide de forma verificable

La situación

Un proyecto propio, no de un cliente: un cronómetro de concentración que observa cuánto se ha inclinado la cabeza respecto a una posición calibrada por el usuario al inicio de la sesión. Necesitábamos un caso en el que las afirmaciones sobre el algoritmo pudieran mostrarse, no describirse.

Qué construimos

Separamos el núcleo de la interfaz y escribimos los umbrales en código, no en la documentación: por debajo de 7° recto, entre 7° y 13° deslizamiento, por encima de 13° mantenido tres segundos activa la alerta háptica, con suavizado exponencial al coeficiente 0,15. Los datos vienen de la interfaz de Apple para los sensores de los auriculares, con tratamiento explícito de la desconexión. El onboarding tiene 24 pasos, de los cuales cuatro piden confirmar los límites antes de dejar al usuario seguir adelante. Construimos a partir del mismo núcleo también una variante de macOS.

Qué salió

La suite de lógica se compila con `swiftc` y se ejecuta en Mac en unos segundos: 160 verificaciones en 16 etapas, todas superadas en la última ejecución. La aplicación se instala y se inicia en el simulador. Cualquier afirmación del párrafo anterior puede verificarse abriendo cuatro líneas de código.

Qué no dice el caso

No está en App Store. La configuración del proyecto tiene el identificador de equipo de Apple vacío, así que el build no puede firmarse para distribución — una falta de inscripción en el programa de Apple, no una falta de funcionalidad. Y todavía una limitación, del producto y no del código: mide la inclinación de la cabeza, no la salud de la columna, y funciona con los auriculares que exponen sensores de movimiento mediante la interfaz de Apple.

Preguntas

Lo que nos pregunta la gente antes de llamar

¿Tenéis una aplicación publicada en App Store, para poder verla?

No. Ninguna de nuestras aplicaciones está en App Store ni en Google Play, y es correcto preguntar eso primero. Lo que podemos mostrar: cinco destinos de aplicación definidos en el mismo proyecto, de los cuales cuatro para iPhone y uno para macOS, que compilan y se instalan en el simulador, más la suite de lógica de 160 verificaciones, ejecutada a petición delante de ti. El bloqueo para la publicación es `DEVELOPMENT_TEAM` vacío en la configuración del proyecto, es decir, la falta de un identificador del Apple Developer Program. En Mac hay una identidad de firma válida, de tipo desarrollo — suficiente para instalar en el propio dispositivo, no para la tienda.

Entonces, ¿de dónde sé que podéis llevar una aplicación hasta la tienda?

De nada, si pides una prueba de publicación — no tenemos una y no la inventamos. Lo que sí puedes verificar es el resto de la cadena: código que compila, pruebas que pasan, archivos de privacidad presentes, permisos declarados, iconos y versiones configurados. El paso que falta es una inscripción de pago en un programa de Apple, hecha a nombre de la empresa que posee la aplicación. En un proyecto de cliente, esa cuenta es del cliente y se abre al principio, justamente para que no sea ese el paso que sorprenda a alguien al final.

¿Nativa o una sola aplicación para iOS y Android?

Depende de los sensores. Si la aplicación lee movimiento, salud, Bluetooth o cámara en tiempo real, nativa: esas interfaces son de la plataforma y cualquier capa intermedia añade retraso y nuevas formas de fallar. Si la aplicación es, en esencia, formularios, cálculos y pantallas de resultados, un solo código cubre iOS, Android y navegador desde un repositorio. Tenemos ambas variantes en el portafolio y las elegimos con un argumento escrito, no por defecto.

¿También hacéis aplicaciones para Android?

Con código común, sí: el mismo proyecto Expo genera builds para Android, con el icono adaptativo y la variante monocroma que exige el sistema, ya configuradas. Android nativo, en Kotlin, no lo tenemos en el portafolio; si un proyecto lo requiere, lo decimos antes, no después de firmar.

¿Cómo comprobáis que la lógica es correcta si no tenéis mi teléfono?

Porque el núcleo no depende de la pantalla. Los archivos de análisis se compilan por separado, con el compilador Swift, y se ejecutan como programa en Mac. La suite actual tiene 160 comprobaciones en 16 etapas y se ejecuta en unos segundos. Lo que no se puede comprobar así — cómo se siente una vibración, cómo se ve una pantalla en un teléfono concreto, cómo se comportan los auriculares cuando salen de una oreja — se prueba en el dispositivo, y se dice cuál es cuál.

¿La aplicación puede leer mis datos de Salud?

Solo si los apruebas, tipo por tipo, en la pantalla de Apple, y solo los declarados. En el código, la política es explícita para cada tipo de dato: unos se quedan solo en el teléfono, otros se leen desde HealthKit, otros se pueden escribir de vuelta como entrenamiento o como sesión de relajación. No se hace diagnóstico, y los datos no llegan a nosotros.

¿Qué pasa con los datos si la aplicación no tiene servidor?

Se quedan en el teléfono. En la aplicación iOS de referencia de nuestro portafolio no existe ninguna llamada de red: la búsqueda de `URLSession` en los fuentes de ese target devuelve cero resultados. El historial se escribe en un archivo local y se puede borrar desde la aplicación. Cuando un proyecto necesita servidor, lo construimos, pero no lo ponemos por reflejo.

¿Podemos tomar una aplicación existente, hecha por otra persona?

Empieza con una verificación de compatibilidad, no con una oferta: qué versión de plataforma apunta, qué dependencias tiene y cuáles de ellas siguen mantenidas, si el build se reproduce en una máquina limpia, quién posee la cuenta de desarrollador y las claves. Hay proyectos en los que la respuesta honesta es que reescribir el núcleo cuesta menos que mantenerlo.

¿También hacéis aplicaciones de escritorio?

En macOS, sí, y desde el mismo núcleo: en nuestro repositorio principal, el target de macOS reutiliza quince archivos de lógica de la aplicación de iPhone, como fuentes compartidos. Windows no está en el portafolio.

En qué se basan las afirmaciones anteriores (11 fuentes)
  1. Varianta web a aplicației cu cod comun răspunde azihttps://longevita-alpha.vercel.app/ · 2026-09-06

10 de ellas son código y archivos de nuestros repositorios. No publicamos su nombre ni la línea: juntos, en una sola página, describirían con demasiada precisión cómo están construidos sistemas que no son solo nuestros. Los repasamos contigo, en el repositorio, a petición — la verificación sigue siendo posible, solo que se hace en una conversación.

¿Qué te gustaría que funcionara mejor?

Cuéntanos tu proceso. Juntos decidimos qué merece la pena construir, qué podemos conectar y cómo verificamos el resultado.

Vamos a hablar