177 lecturas Nueva Historia

En 2025, la música local en el iPhone es una pesadilla, así que construí mi propio camino

por Oleg Pustovit12m2025/05/22
Read on Terminal Reader

Demasiado Largo; Para Leer

En 2025, jugar tu propia música en un iPhone es sorprendentemente difícil, a menos que pagues a Apple o navegues por un laberinto de limitaciones.
featured image - En 2025, la música local en el iPhone es una pesadilla, así que construí mi propio camino
Oleg Pustovit HackerNoon profile picture
0-item

En 2025, jugar tu propia música en un iPhone es sorprendentemente difícil, a menos que pagues a Apple o navegues por un laberinto de limitaciones.Así que construí mi propio reproductor desde cero, con búsqueda de texto completa, soporte de iCloud y una experiencia local-first.

En 2025, jugando a su propiomusic on an iPhone is surprisingly hard, a menos que pagues a Apple o navegues por un laberinto de limitaciones. Así que construí mi propio jugador desde cero, confull text search, deiCloud support, y alocal-first experience. elGitHub enlaces

Por qué he creado mi propio reproductor de audio

Como muchas personas, he recogido demasiadas suscripciones, algunas a través de Apple (iCloud, Apple Music), otras se perdieron en plataformas aleatorias (como Netflix, que olvidé que todavía estaba pagando).

Inicialmente pensé que seguiría usando la Biblioteca de Música de iCloud para la sincronización de música entre dispositivos, pero una vez que cancelé la suscripción a Apple Music, la sincronización dejó de funcionar.behind a paywallTécnicamente se puede recuperar a través deJuegos de iTunes($ 24.99 por año). Match sólo almacena copias AAC de 256 kbps en línea; sus archivos originales permanecen en el lugar a menos que elija reemplazarlos. En un Mac moderno, lo hace todo en la aplicación Music. Sin ninguna suscripción, la sincronización en la nube se ha ido, y está de vuelta a la sincronización de cable/Wi-Fi.

Juegos de iTunes

Frustrado por la falta de opciones, fui albuilder routeSi compré un dispositivo de computación (iPhone en este caso), ¿qué me impide construir exactamente lo que necesito con el código para usarlo?En este artículo, quiero compartir mi viaje completo de frustraciones hacia la creación de una funcionalidad básica de reproductor de música: cargar archivos de audio, organizar y reproducirlos, pero sobre todo, quería recordarme,Este es todavía un ordenador de propósito general, debería ser capaz de hacer que haga lo que quiero.

Lo que Apple (y otros) ofrecen hoy

Antes de escribir mi propia aplicación, exploro las opciones oficiales y de terceros para la reproducción de música offline.

Aplicaciones incorporadas de Apple

Apple te permite tecnicamente reproducir música directamente desde iCloud a través de la aplicación de archivos, pero su funcionalidad no está diseñada para escuchar música.lacks essential featurescomo la gestión de listas de reproducción, la clasificación de metadatos o las filas de reproducción. Si bien soporta la reproducción de música, es muy limitada y generalNo una buena experiencia de usuario.

No una buena experiencia de usuario

Aplicaciones de terceros

Fui a la tienda de aplicaciones para buscar aplicaciones cool que resuelvan mi problema, mientras que hay muchos de ellos, muchos dependen desubscription-based pricing, un modelo cuestionable para una aplicación que simplemente reproduce archivos que los usuarios ya poseen.DopplerHe jugado con él durante un ensayo, pero el UX está construido alrededor de la gestión de álbumes. La búsqueda no fue tan buena, y la funcionalidad de importación de iCloud fue lenta y difícil de usar en un gran número de carpetas ancladas.

Going Builder Mode: Mi viaje técnico

Dicho esto, decidí crear mi propio reproductor de música ideal que resuelva mis puntos de dolor:

  • Busca de texto completo flexible en todas las carpetas de iCloud, para que pueda seleccionar e importar una carpeta con música o archivos específicos rápidamente.
  • Funcionalidad en la gestión de la música al menos en par con la aplicación oficial de música: cola, gestión de listas de reproducción y clasificación por álbumes, etc.
  • Interfaz familiar y amigable.

Reaccionar primero con los nativos

Hace unos años, me gustó la sintaxis (me sentí más cerca de TypeScript) y aprecié la seguridad de la memoria similar a Rust, pero sin nativoasync/awaitEn ese momento, la escritura de código simultáneo en comparación con Go o JS/TS se sintió clunky y boilerplate-pesado. esa experiencia me dejó frustrado, por lo que cuando revisité este proyecto, inicialmente alcancé por algo más familiar.

Dicho esto, fui con React Native o Expo, con la esperanza de reutilizar mi experiencia de desarrollo web y conectar una interfaz de usuario del jugador de las plantillas existentes. Construir la interfaz de usuario de reproducción fue sencillo; hay numerosos ejemplos de código abierto y vídeos de tutoria sobre la construcción de jugadores de música que se ajusten a mis necesidades.Proyecto de templos de Gionatha Sturba, porque parecía tener todas las características que necesito para mi aplicación.

Attempting to build an app with React Native/Expo

El acceso al sistema de archivos y la sincronización de archivos en la nube alcanzan grandes obstáculos: bibliotecas comoexpo-filesystemsoporta la selección básica de archivos, pero la travesía recursiva a través de directorios de iCloud profundamente ancladosoften failed or even caused app crashesEsto hizo claro que aJavaScript-based approach introduced more complexitymás que simplemente trabajar con las APIs nativas de Apple, incluso si significaba una curva de aprendizaje más rígida.

El sandboxing de iOS impide que las aplicaciones lean archivos sin permiso explícito del usuario, lo que significó que React Native no podía acceder a carpetas externas de manera confiable.

Cambiar a SwiftUI

Yo fui conSwiftUIen lugar de UIKit o storyboards porque quería unclean and declarative UIuna capa que se mantendría fuera del camino mientras me enfocaba en la lógica del dominio y la sincronización de datos.Con características modernas como async/await e integración conSwift Actors, encontré que es más fácil gestionar el flujo de datos y la concurrencia. SwiftUI también definitivamente facilitó la estructuración de la aplicación en componentes ViewModel aislados, lo que a su vez me ayudó a obtener mejores resultados de LLMs como OpenAI o1 y DeepSeek. LLMs podrían producir código UI puro o código de vinculación de datos sin introducir interdependencias desordenadas.

Arquitectura de aplicaciones y modelo de datos

Pasemos a la arquitectura de la aplicación que he creado: usé SQLite para almacenamiento de datos persistente y abordé la arquitectura de la aplicación como una aplicación de servidor simple. Evité CoreData porque necesitaba un control estricto sobre el esquema, las consultas en bruto y especialmente la búsqueda de texto completo. el soporte FTS5 integrado de SQLite me permitió agregar búsquedas fuzzy rápidas sin arrastrar motores de búsqueda externos pesados o construir mi propia capa de indexación.

Tres pantallas principales

The app consists of 3 screen/modes:

  1. Importación de bibliotecas. Aquí es donde se agrega su carpeta de biblioteca de iCloud. La aplicación escanea cada carpeta para archivos de audio e inserta cada camino en una base de datos SQLite. De esta manera, puede tener plena flexibilidad en la búsqueda, la adición de carpetas y subcarpetas. el selector de archivos nativo de Apple es muy clunky; no puede seleccionar múltiples directorios que ha buscado por palabra clave y luego también un montón de archivos en un solo paso. simplemente no está diseñado para hacer eso.
  2. Gestión de bibliotecas. Aquí es donde puedes administrar las canciones añadidas y organizar listas de reproducción. Para la mayor parte, he reflejado la forma en que Apple hizo eso en su app de música, y fue lo suficientemente bueno para mis necesidades.
  3. Esta parte de la aplicación gestiona la gestión de la cola (repeat, shuffle), etc., y la funcionalidad de reproducción, parada y canción siguiente.

Aquí se muestra un diagrama de flujo de usuario simple:

User flow diagram

User flow in practice:Cuando la aplicación se lanza con una biblioteca vacía, aterriza en la pestaña de sincronización, mostrando un gran botón "Añadir fuente de iCloud". Seleccione una carpeta allí, y la pantalla de sincronización muestra una barra de progreso mientras camina por el árbol. tan pronto como finalice la indexación, te cambia a la pestaña de la biblioteca, cuyas primeras listas de pantallaPlaylists / Artists / Albums / SongsSubir a cualquier lista, pulsar una pista, y un Mini-Player aparece en la parte inferior; pulsar esa mini-bar para abrir el reproductor de pantalla completa con shuffle, repetir, reordenar la cola y el volumen. Deslizar o pulsar el icono cerrado, y usted está directamente de vuelta a la Biblioteca mientras la reproducción continúa. En cualquier momento que necesite más música, saltar de nuevo a Sincronizar, pulsar el "+" en la barra nav, seleccionar otra carpeta, y el servicio de importación fusionará nuevas canciones en el fondo, sin necesidad de reinicio.

Backend-Like Layer Lógico

Teniendo un fondo web / nube y enviando un montón de código de servidor mientras trabajaba en startups, fui con unbackend-like architecturepara la aplicación móvil. El dominio completo/la capa lógica se separó de laView and View-Model layerDebido a que tuve que hacer elcloud syncing, metadata parsingaspecto de la aplicación y tener acceso a datos limpios a un DB de SQLite.Aquí está un diagrama de arquitectura de capas aproximada que usé aquí:

Layered architecture diagram

How the layers talk:SQLite se sienta en la parte inferior, almacenando líneas de canciones crudas e índices FTS. Luego los repositorios envuelven la base de datos y exponen las APIs async.domain actors, actores Swift que poseen todas las reglas de negocio (importación, búsqueda, lógica de cola) para que las mutaciones de estado permanezcanthread-safeViewModels se suscriben a los actores, transforman los datos en estructuras preparadas para la interfaz de usuario, y las vistas de SwiftUI simplemente muestran lo que reciben.nicely decoupled.

Implementación de la búsqueda de texto completo con SQLite

Como mencioné anteriormente, es una suerte que puedas importar una versión de SQLite con capacidades FTS: a partir de alrededor de iOS 11, está disponible fuera de la caja.without extra setupEsto facilitó la integración de la búsqueda fuzzy en mi biblioteca de músicawithout any third-party dependenciesAdemás, usé la biblioteca SQLite.swift para consultas regulares (que funciona como una especie de constructor de consultas con seguridad de tiempo de compilación); sin embargo, para consultas FTS, tuve que recurrir a declaraciones SQL regulares.

La de SQLiteFT5La extensión terminó siendo una de las piezas más valiosas de la arquitectura.Me permitió consultar nombres de archivos y metadatos como artista, álbum y título sin una infraestructura de indexación adicional.

Creación de las mesas FTS

Domain

Swift actor / repo

FTS5 table

Columns that get indexed

Library songs

SQLiteSongRepository

songs_fts

artist, title, album, albumArtist

Source-browser paths

SQLiteSourcePathSearchRepository

source_paths_fts

fullPath, fileName

Canciones de Biblioteca

SQLiteSongRepository

songs_fts

artist, detitle, dealbum, dealbumArtist

Pautas de navegación

SQLiteSourcePathSearchRepository

source_paths_fts

fullPath, defileName

Utilizo dos tablas FTS5: una para canciones indexadas (artista/título/álbum) y una para caminos de archivos durante la importación de carpetas.songs, desource_pathsEl FTS esread-only for the UITodos los escritos ocurren dentro de los repositorios para que nada se escape a través de las grietas.

Crear el índice de búsqueda

El FTS5 integrado de SQLite hace que las búsquedas rápidas sean fáciles.Aquí hay una definición de tabla simple que he utilizado:

try db.execute("""
CREATE VIRTUAL TABLE IF NOT EXISTS songs_fts USING fts5(
  songId UNINDEXED,
  artist, title, album, albumArtist,
  tokenize='unicode61'
);
""")

Yo usabaunicode61Tokenizer para garantizar que se trate de una amplia variedad de caracteres.Las claves no buscables están marcadas conUNINDEXEDPor lo tanto, no bloquean el diccionario.

Actualizar los datos de manera fiable

Para mantener las cosas sencillas y seguras, he envuelto las actualizaciones e insertado en las transacciones. Esto asegura que el índice de búsqueda nunca salga de sincronización, incluso si la aplicación se cae o se interrumpe.

func upsertSong(_ song: Song) async throws {
    db.transaction {
        // insert or update main song data
        // insert or update search index data
    }
}

Buscar con la búsqueda Fuzzy

Para una búsqueda fácil de usar, añado el soporte de wildcard automáticamente.Si escribe "lumine", busca "lumine*" internamente, dando resultados instantáneos incluso con consultas parciales.

También utilizo el ranking inteligente integrado de SQLite (bm25) para devolver resultados más relevantes sin complicaciones adicionales:

SELECT s.*
FROM songs s JOIN songs_fts fts ON s.id = fts.songId
WHERE songs_fts MATCH ?
ORDER BY bm25(songs_fts)
LIMIT ? OFFSET ?;

En general, el uso de SQLite crudo me dio la flexibilidad que necesitaba: esquema predictible, acceso local primero y poderosa búsqueda de texto completo, sin introducir dependencias de red o servicios externos.

Trabajar con archivos y bookmarks

En iOS, las aplicaciones pueden almacenar marcadores persistentes para ubicar los archivos, perosecurity-scoped bookmarks, que otorgan acceso extendido a los archivos fuera de la caja de arena de la aplicación, sólo están disponibles enmacOSLas aplicaciones de iOS pueden usar marcadores regulares para recordar los caminos de archivo y solicitar el acceso de nuevo a través del selector de documentos, pero ese acceso no está garantizado para persistir en silencio.Documentación de Bookmark de Apple.

Para mitigar esto, implementé un mecanismo de retroalimentación que copia los archivos en elapp's own sandboxed containerEsto evita el ciclo de vida frágil de los marcadores de seguridad que pueden romperse silenciosamente si iOS restablece los permisos.Al copiar archivos de forma proactiva en el fondo, mientras el marcador es válido, no hay riesgo de acceder a referencias de archivos de audio inválidas.

Este enfoque también mejora la velocidad de indexación.Puedo escanear la estructura de la carpeta una vez (mientras el acceso está activo), importar solo archivos de audio relevantes, y cruzar de forma segura directorios profundamente anclados.Pero reproducir de forma confiable los archivos de audio individuales desde ubicaciones externas, especialmente después de que el dispositivo se reinicie,Un problema sin resolver para míEsto destaca cómounder-supportedeste caso de uso es, incluso para las aplicaciones nativas, y lo complejo que aún eshandle file access reliably on iOS.

Desarrollar el Playback y la UI

Metadatos Parsing

Para analizar metadatos de archivos de audio, usé elAVFoundation frameworkEn concreto, elAVURLAssetclase, que permite la inspección de metadatos de archivos de medios, como título, artista de álbumes, etc. Mientras que el análisis de metadatos es manejado por el SDK nativo, ciertos campos como los números de seguimiento tienen que buscar manualmente las etiquetas ID3.Búsqueda en GitHubpara encontrar ejemplos, ya que la documentación oficial carecía de cobertura para casos de raíz.

Reproducción de audio con AVFoundation

Después de que la biblioteca se indexe, implementar un reproductor de audio se siente bastante simple: sólo tiene que inicializar una instancia de audio.AVAudioPlayerAdemás, para las características de calidad de vida: para tocar música desde el centro de control, tuve que implementar elAVAudioPlayerDelegateprotocolo y también se ha adherido a los de AppleMPRemoteCommandCenter, que permite a los desarrolladores responder a los controles de reproducción a nivel del sistema.

Reflexiones: Apple, Lock-In para desarrolladores y el futuro

Aquí está lo que se destacó durante el desarrollo:

Los malos

Xcode's limitations remain frustrating.Las previsións de SwiftUI en tiempo real son definitivamente un paso adelante, pero la experiencia general de desarrollo todavía no está en par con lo que Flutter ofreció hace cinco años: integración de VSCode estrecha, cargas de simulador en tiempo real y herramientas de depuración familiares.

Lack of editor flexibility.Configurar el soporte de Language Server Protocol (LSP) para Swift en Neovim o VSCode requiere herramientas adicionales comoxcode-build-server, y todavía no coincide completamente con la experiencia del desarrollador de los ecosistemas web-first.

Some corners of Apple's SDK still live in Objective-C land.La búsqueda de archivos Spotlight, por ejemplo, sólo se expone a través deNSMetadataQuery, que utiliza Key-Value Observing (KVO) y teclas de cuerdas, no hay todavía un envasador amigable con Swift.

SwiftUI's declarative UI is great, but debugging iCloud interactions still requires manual mocks.Las previstas de SwiftUI no pueden emular comportamientos de aplicaciones completos que involucren derechos de iCloud, por lo que tiene que burlarse de las interacciones en la nube manualmente, una molestia menor pero notable.

El Buen

Async/await.Por último, puedo escribir código simultáneo I/O-bound como un imperativo sin llamadas molestas.Esto es una gran victoria, y aprecio lo fácil que es escribir incluso el código de sincronización en Actors y llamarlo como lo haces en los ecosistemas de JavaScript.

Plethora of native libs.Sí, no estás limitado por vínculos de código abierto como en los ecosistemas React Native/Flutter. Aquí tienes mucho más libertad para desarrollar algo "más serio" que reemplazar el sitio web de tu empresa/producto (debido a una mala experiencia de inicio móvil).

SwiftUISí, el enfoque de estilo React para construir UI da más productividad y espacio para explorar.

Resumen: La construcción debería ser más fácil

Después de 1,5 semanas de hackeo, pude obtener la pieza de software que satisface exactamente mis necesidades: unalocal/offline music playerque puede importar archivos de audio desde el almacenamiento en la nube.

Pero los desarrolladores rápidamente se dan cuenta de que no pueden desplegar fácilmente aplicaciones en sus propios dispositivos en estos días y se olvidan de ello: las aplicaciones solo se ejecutan para7 days without a dev certificate, y después de eso, tiene que reconstruirlo, a menos que pague $ 99 a Apple para inscribirse en el programa de desarrollo.

7 días sin un certificado de Dev

Incluso después de laDMA Act in the EULos usuarios de la UE ahora pueden instalar aplicaciones de mercados de terceros directamente desde el sitio de un desarrollador, pero sólo si ese desarrollador todavía está inscrito en el programa de $ 99 / año de Apple y acepta las Condiciones Alternativas de Apple.

Esto en última instancia no tiene sentido.Una empresa de tecnología innovadora pone activamente barreras en el desarrollo de aplicaciones democratizadas.Limitaciones notables en iOS: incluso después de las actualizaciones de 16-18.x de Apple, los PWA de iOS todavía se ejecutan dentro de la caja de arena de Safari. Obtienen WebGL2 y web-push, pero no obtienen Web Bluetooth/USB/NFC, Background Sync, o más de ~50MB de almacenamiento garantizado. WebGL corre a través de Metal shim, por lo que las tasas de marco del mundo real a menudo siguen las aplicaciones nativas de Metal; esto es lo suficientemente bueno para la interfaz de usuario, pero no para los juegos 3D de AAA.

Hoy en día, la IA ha reducido la complejidad del desarrollo de software moderno al permitir a cualquiera abordar tecnologías desconocidas al proporcionar todo el conocimiento necesario de una manera accesible.Puede ver claramente cómo el desarrollo web ha recibido más interés de personas no técnicas que tienen una manera de construir sus ideas sin especializarse en una pluralidad de tecnologías.Pero cuando se trata de aplicaciones móviles, sólo tiene que jugar por las reglas artificiales.Incluso si lo has construido tú mismo, para ti mismo, Apple todavía tiene la última palabraantes de que puedas ejecutarlo durante más de una semana.La misma compañía que una vez empoderó a desarrolladores independientes ahora imponetight restrictions that hinder personal app developmentLa IA ha hecho más fácil que nunca construir nuevas herramientas, a menos que esté construyendo para iOS, donde la puerta todavía está cerrada.

Enlaces relacionados

  • iTunes Match - Soporte de Apple
  • Documentación de seguridad - Apple Docs
  • FTS5 - Documentación SQLite
  • Reproductor de música Doppler - App Store
  • Documentación de EXPO FileSystem
  • Información del programa de desarrolladores de Apple (7 ediciones de día)
  • Comunidad de Apple: Aplicación de archivos y reproducción de MP3


Trending Topics

blockchaincryptocurrencyhackernoon-top-storyprogrammingsoftware-developmenttechnologystartuphackernoon-booksBitcoinbooks
OSZAR »