Communitygithub.com

byteratio/iphone-dev

Convenciones para desarrollo de aplicaciones nativas para iPhone — SwiftUI + SwiftData local-first, generación de proyectos con XcodeGen, bucles CLI-only de compilación/prueba/despliegue (simulador por defecto, despliegues firmados en dispositivos mediante devicectl), XCTest con cobertura visible, y problemas de firma con cuentas personales gratuitas. Úsalo al crear una aplicación iOS/iPhone, añadir objetivos iOS o bucles Makefile a un proyecto, depurar problemas de firma/provisionamiento/despliegue en Xcode, o portar la lógica de una aplicación existente a un cliente nativo en Swift.

¿Qué es iphone-dev?

Esta skill proporciona un conjunto completo de convenciones y mejores prácticas para el desarrollo de aplicaciones nativas para iPhone con SwiftUI y SwiftData, optimizadas para equipos pequeños y cuentas gratuitas de Apple sin distribución en la App Store. Está diseñada para desarrolladores que trabajan principalmente desde la línea de comandos, utilizando XcodeGen para la generación de proyectos y evitando el uso directo del IDE de Xcode para la mayor parte del flujo de trabajo. La skill cubre desde la arquitectura predeterminada (SwiftUI + SwiftData, local-first) hasta la generación de proyectos, el bucle de desarrollo (compilar en simulador sin firma, probar con cobertura, desplegar en dispositivo físico), y las pruebas con XCTest. Incluye también una sección detallada sobre los problemas comunes de firma con cuentas personales gratuitas, que han costado tiempo a muchos desarrolladores. Además, ofrece una guía para la sincronización de datos con un servidor backend existente, dividida en cuatro niveles de complejidad (cliente ligero, espejo de instantáneas, bandeja de salida limitada, sincronización bidireccional completa), permitiendo elegir la opción más adecuada según las necesidades de la aplicación. La skill es compatible con plataformas como Claude Code, Cursor y Codex, y está diseñada para ser utilizada en flujos de trabajo basados en Makefiles.

Compatible con~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/byteratio/skills/tree/main/plugins/hechtch-skills/skills/iphone-dev

Preguntar en tu IA favorita

Abre un nuevo chat con esta habilidad de agente ya precargada.

Documentación

Desarrollo de aplicaciones para iPhone

Convenciones destiladas de la publicación de una aplicación SwiftUI de principio a fin, desde un repositorio vacío hasta una compilación firmada ejecutándose en un teléfono físico.

Contexto asumido: aplicaciones a pequeña escala, una cuenta personal gratuita de Apple, sin distribución en la App Store. Un equipo de desarrolladores de pago cambia varias reglas a continuación: la sección de firma indica cuáles.

Valores predeterminados de arquitectura

  • SwiftUI + SwiftData, local-first. Una aplicación pequeña no debería requerir un servidor accesible. Los datos residen en el dispositivo en SwiftData; las llamadas de red son solo para APIs públicas (https, sin excepciones ATS). Si la aplicación comienza como un cliente ligero para un backend existente, espera el giro de "¿podemos eliminar el servidor?" — porta la lógica del backend a funciones Swift puras sobre los arrays de SwiftData en lugar de mantener un servidor en funcionamiento para un solo teléfono.
  • Modelado con SwiftData: relaciones de objetos reales, no claves foráneas enteras. @Attribute(.unique) para claves naturales. Los arrays to-many de SwiftData no preservan el orden: añade un campo sortOrder y una propiedad computada sortedX cuando el orden importe. Fechas como Date, no cadenas. Enums con rawValue String y conformidad Codable.
  • Cambios de esquema en una instalación existente: agregar modelos o propiedades opcionales migra ligeramente de forma silenciosa en el siguiente inicio; los cambios de nombre, eliminaciones o cambios de tipo sin un SchemaMigrationPlan hacen que el almacenamiento falle al abrirse; la aplicación desplegada entonces falla al inicio con los datos del usuario intactos pero secuestrados. Los redespliegues (mismo ID de paquete) nunca eliminan el contenedor de datos; solo la eliminación de la aplicación lo hace. Planifica una ruta de exportación/copia de seguridad antes de que los usuarios acumulen datos reales.
  • Las vistas se comunican directamente con @Query + modelContext. Sin capa de Store/repositorio a menos que algo necesite genuinamente almacenamiento en caché. La lógica pura (coincidencia, análisis, importación) reside en namespaces de enum (enum Foo { static func … }) — comprobable sin UI.
  • Objetivo de despliegue: el actual menos uno a menos que una API necesaria indique lo contrario. Un objetivo, TARGETED_DEVICE_FAMILY: "1", retrato a menos que la aplicación justifique la rotación.

Generación de proyectos — XcodeGen, nunca un .xcodeproj comprometido

ios/project.yml es la fuente de verdad; el paquete .xcodeproj es generado y excluido con git (también excluye ios/build/ y el Info.plist generado). Regenera después de agregar o eliminar archivos: xcodegen recorre los directorios de fuentes, por lo que las ediciones en archivos existentes no necesitan nada.

  • Instala xcodegen desde el archivo zip de la versión de GitHub (PREFIX=~/.local ./install.sh) — sin Homebrew requerido, funciona en una Mac bloqueada.
  • Los objetivos de pruebas unitarias necesitan GENERATE_INFOPLIST_FILE: YES o el paquete de prueba falla al firmar.
  • Define el esquema en project.yml con gatherCoverageData: true y el objetivo de prueba adjunto, o xcodebuild test no tiene nada que ejecutar.

El bucle de desarrollo — solo CLI, simulador por defecto

Cada proyecto iOS obtiene estos objetivos de Makefile. Parametriza el nombre del simulador, el ID del dispositivo y el ID del equipo como variables ?= para que nada específico de la máquina esté codificado:

ObjetivoQué hace
ios-projectxcodegen generate + abrir en Xcode
ios-simcompilar sin firma para simulador, iniciar sim, instalar, lanzar — el bucle predeterminado; cero firma, cero solicitudes de contraseña
ios-sim-seedios-sim, luego relanzar con --seed-demo
ios-testxcodebuild test en el simulador + informe de cobertura por objetivo con xccov
ios-deploycompilación firmada para el teléfono conectado + instalación con devicectl + lanzamiento

ios-test imprime la cobertura en cada ejecución: la regla de la casa es que make test siempre muestra el número, sin umbral fijo adjunto.

Compilaciones para simulador: CODE_SIGNING_ALLOWED=NO está bien para verificaciones de compilación generic/platform=iOS; los destinos del simulador no necesitan ninguna firma. Recuerda que el simulador y el teléfono tienen bases de datos separadas.

Comodidades de depuración que siempre valen la pena

  • Sembrador de datos de ejemplo (DemoData.swift, #if DEBUG): conjunto de datos curado con campos de caducidad/fecha calculados relativos a .now, idempotente (re-ejecutar no agrega nada), expuesto de tres maneras: un botón en la sección "Desarrollador" de Ajustes, un argumento de lanzamiento --seed-demo verificado mediante ProcessInfo.processInfo.arguments, y el objetivo ios-sim-seed. Agrega una prueba que verifique que la siembra ejercita los estados principales de la aplicación para que no pueda pudrirse silenciosamente.
  • Selectores con búsqueda en lugar de selectores de rueda una vez que una lista puede exceder un par de docenas de entradas (los conjuntos de datos importados garantizan esto).
  • Funciones de cámara/escáner: verifica DataScannerViewController.isSupported && .isAvailable y envía una alternativa de entrada manual: se degrada con gracia también en el simulador.

Pruebas

  • XCTest en el simulador; al portar lógica de otra pila, porta también el conjunto de pruebas de referencia para que la semántica esté fijada entre lenguajes.
  • Ayudante compartido: makeInMemoryContext() que construye un ModelContainer con isStoredInMemoryOnly: true; clases de prueba @MainActor con setUp() async throws.
  • Lee el resultado de aprobado/reprobado del paquete de resultados: xcrun xcresulttool get test-results summary --path build/test.xcresult.

Firma y despliegue: los problemas (cada uno costó tiempo real)

  • El ID del equipo NO es el paréntesis en security find-identity — ese es el ID del propio certificado. Obtén el ID real del equipo desde un perfil de aprovisionamiento (security cms -D -i <profile> → el prefijo application-identifier) o desde el panel de Cuentas de Xcode. El ID incorrecto da un error engañoso "No Account for Team".
  • -allowProvisioningUpdates no puede ver la sesión del ID de Apple desde una terminal simple. Crea el perfil de aprovisionamiento una vez en la GUI de Xcode (Firma y Capacidades → establecer Equipo → Intentar de nuevo); después de eso, las compilaciones puramente desde CLI funcionan con DEVELOPMENT_TEAM=<id> CODE_SIGN_STYLE=Automatic.
  • Baile del primer dispositivo: habilita el Modo Desarrollador en el teléfono (Ajustes → Privacidad y Seguridad; el interruptor aparece solo después de que Xcode haya hablado con el dispositivo; reinicios) → confía en la computadora → después de la primera instalación, confía en el certificado de desarrollador (Ajustes → General → VPN y Gestión de Dispositivos). El error "your team has no devices" de Xcode generalmente significa que el intento de registro ocurrió mientras el teléfono se reiniciaba o estaba bloqueado — selecciona el teléfono como destino de ejecución y reintenta.
  • Solicitudes de llavero en cada compilación: haz clic en Siempre Permitir en el diálogo del llavero de codesign una vez; las solicitudes de contraseña por compilación se detienen.
  • Límites del equipo personal gratuito: las instalaciones caducan después de 7 días (redespliega para volver a firmar), máximo 3 aplicaciones laterales, sin notificaciones push, sin App Groups. Un equipo de pago elimina los cuatro: si la aplicación necesita push o App Groups, ese es el desencadenante para obtener uno.
  • CLI de despliegue/lanzamiento: xcrun devicectl list devices, xcrun devicectl device install app --device <id> <path>.app, … device process launch --device <id> <bundle-id>.

Inicio en una Mac nueva (compatible con headless)

  1. Xcode desde la App Store (abre macappstore://apps.apple.com/app/id497799835).
  2. sudo xcode-select -s /Applications/Xcode.app && sudo xcodebuild -license accept && sudo xcodebuild -runFirstLaunch — necesita un administrador; en una cuenta estándar, primero arregla la membresía de administrador (su admin -c 'sudo dseditgroup -o edit -a <usuario> -t user admin').
  3. xcodebuild -downloadPlatform iOS — el SDK de iOS y el runtime del simulador es una descarga separada de varios GB desde Xcode 15; las compilaciones fallan con "iOS X.Y is not installed" sin él.
  4. DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer funciona como una anulación por comando antes de que se arregle xcode-select.
  5. xcodegen desde el archivo zip de la versión en ~/.local (ver arriba).

Clientes complementarios para un servidor existente: niveles de sincronización

Cuando la aplicación de iPhone se une a una aplicación que ya tiene un servidor + aplicación web (el servidor sigue siendo la única fuente de verdad), elige el nivel más barato que permita el caso de uso del teléfono. Pregunta primero "¿necesita el teléfono funcionar fuera de la red del servidor?" y "¿captura o edición completa?":

  1. Cliente ligero — sin almacén local; el teléfono llama a la API existente. Correcto cuando la conectividad está garantizada.
  2. Espejo de instantáneas — caché de SwiftData reconstruida completamente a partir de una extracción JSON completa (las bases de datos de un solo usuario son pequeñas). Sin fusión → sin lápidas, sin marcas de tiempo por fila, sin motor de conflictos; las eliminaciones/ediciones del lado del servidor llegan gratis. Las fotos se cargan de forma diferida mediante la caché de URL.
  3. Bandeja de salida limitada — creación sin conexión limitada a hijos de registros que ya existen (registros, notas, fotos contra padres conocidos). Los padres llevan IDs reales del servidor, por lo que la reproducción son llamadas API simples: los esquemas con PK enteros necesitan ninguna migración a UUID. Evento de sincronización = enviar bandeja de salida, luego extraer instantánea (las propias capturas vuelven confirmadas). Muestra huérfanos 404 ("N no pudo sincronizarse"), nunca elimines silenciosamente. Muestra una insignia de pendientes + una marca de tiempo de la última sincronización. Auto-sincronizar solo cuando la dirección del servidor fijada por el usuario responda, nunca explorar redes externas.
  4. Sincronización bidireccional completa (UUIDs, lápidas, endpoints delta, LWW/CRDT) — solo con evidencia de que los niveles 1–3 no son suficientes; el rediseño comienza del lado del servidor (UUIDs acuñables por el cliente, upserts idempotentes, changes?since= + lápidas) antes de escribir cualquier Swift.

Los niveles 2 y 3 se combinan bien: un espejo de instantáneas para lecturas más una bandeja de salida limitada para capturas cubre "funciona en casa, captura en cualquier lugar" sin ninguna de la maquinaria del nivel 4.

Higiene del proyecto

  • Los hechos específicos de la máquina y del dispositivo (ID del equipo, UDID del dispositivo, nombre del simulador) van en variables ?= del Makefile o en las notas del propio proyecto — nunca codificados en scripts, y nunca en esta skill.
  • Mantén un documento plans/<tema>.md para cada fragmento de trabajo en curso y un CHANGELOG.md de nivel superior para lo que se ha enviado; mueve un plan a plans/done/<tema>.md con un encabezado "Entregado en <versión> — " una vez que se haya completado.
  • Tamaño de cada fragmento de plan para que termine con algo ejecutable en un teléfono o simulador. Un fragmento de iOS que no se pueda lanzar no se puede revisar.

Individual skills in this repo

This repo contains 5 individual skills — each has its own dedicated page.

byteratio/example-skill

Template skill for this marketplace. Use as a starting point when adding a new skill — copy this plugin directory, rename it, and replace this description with the specific trigger conditions for your skill (what the user says or does that should invoke it).

byteratio/kanban-plans

Track multi-session plans on a locally-running kanban board (github.com/hechtch/kanban) via its agent REST API. Claim a plan, move it through todo/doing/blocked/awaiting_merge/done, leave notes, and set the git branch. Use at the start of any non-trivial multi-session plan, when resuming such a plan, or when the user asks what's on the board or where a plan stands.

byteratio/password-generator

Generates secure, memorable passwords using 3 random dictionary words with leet-speak substitutions. Use when the user asks to generate a password, create a new password, or needs a secure passphrase.

byteratio/security-sweep

Investigate whether a project (or every repo on the machine) is exposed to known and actively-exploited dependency vulnerabilities. Combines a deterministic per-ecosystem audit (npm audit, govulncheck, pip-audit, osv-scanner) with live web research into recent/active supply-chain incidents, then checks each project's lockfiles directly — the leading-indicator check that `npm audit` misses. Use when the user asks to "investigate security", "check for vulnerable dependencies", "are we affected by <a named CVE / package compromise>", "scan the projects for supply-chain issues", or wants a recurring security sweep.

byteratio/ux-agents

Scaffold persona-based UX testing agents for a web app — project-scoped .claude/agents/<persona>-ux.md files that drive a real browser via Playwright, walk user journeys as a specific persona, and report tagged friction findings. Use when setting up UX review automation, when the user asks what a specific user segment would think of the app, or after the user accepts an offer to add persona testing.

Skills relacionados