O player de áudio que eu mesmo criei
(nexo.sh)- Mesmo em 2025, ainda há muitas restrições para reproduzir livremente músicas em MP3 no iPhone
- Os apps da Apple e de terceiros em sua maioria exigem pagamento ou deixam a desejar em usabilidade
- O app feito pelo próprio autor oferece busca full-text, suporte ao iCloud e um ambiente local-first
- Abordagens cross-platform como React Native tinham limitações por restrições do sistema de arquivos e problemas de estabilidade
- Com SwiftUI e uma arquitetura baseada em SQLite, foi possível criar uma experiência de gerenciamento de música independente e altamente expansível
Visão geral
Para resolver por conta própria o incômodo de ainda ser difícil, mesmo em 2025, reproduzir livremente no iPhone arquivos MP3 que o próprio usuário possui, o desenvolvedor apresenta o processo e o resultado de criar ele mesmo um app de player de música. Enquanto os serviços musicais da Apple e os apps externos impõem diversas restrições e modelos pagos, o app implementado diretamente oferece uma experiência otimizada para gerenciar e reproduzir arquivos musicais do usuário.
Por que criar um player de música por conta própria
- Recursos de sincronização em nuvem como Apple Music e iCloud Music Library só funcionam mediante assinatura de serviços pagos
- Ao cancelar a assinatura, a sincronização automática e o acesso à pasta de músicas ficam totalmente bloqueados
- Isso levou à percepção da falta de direito de propriedade efetivo sobre a integração da biblioteca musical existente e o uso geral do dispositivo
- A ideia era concretizar a autodeterminação de que “num smartphone já comprado, também é possível criar por conta própria as funções realmente necessárias”
Análise das soluções de reprodução musical da Apple e de terceiros
App nativo da Apple
- É possível reproduzir arquivos de música em pastas do iCloud usando o app Files, mas faltam funções básicas como gerenciamento de playlists, ordenação por metadados e manipulação da fila
- A experiência oferecida não é otimizada para ouvir música
Apps de terceiros
- Há vários apps externos na App Store, mas muitos seguem um modelo de cobrança por assinatura, e o nível de recursos varia bastante entre eles
- Existem também apps pagos com compra única, como o Doppler, mas a experiência de busca e importação em pastas grandes do iCloud ainda não é fluida
A jornada técnica rumo ao “modo construtor”
- O autor decidiu que precisava criar ele mesmo um app de player de música
- Recursos desejados: busca full-text rápida em toda a pasta do iCloud, recursos de gerenciamento musical no nível de um app oficial de música (fila, playlists, ordenação etc.) e uma interface intuitiva
Primeira tentativa com React Native
- Por incômodos anteriores com a experiência em Swift, o autor preferia React Native/Expo
- O UI foi implementado sem grandes problemas com ajuda de templates open source, mas surgiram crashes e limitações funcionais no tratamento de acesso e sincronização do sistema de arquivos (pasta do iCloud)
- Ao perceber que, pelas políticas de sandbox do iOS, não é possível acessar pastas externas sem permissões explícitas, ele migrou para Swift
Por que escolher SwiftUI
- Aproveitamento do paradigma declarativo de UI do SwiftUI, além de suporte moderno a async/await e Swift Actor
- Com separação rigorosa entre UI e lógica de dados, foi possível implementar um fluxo de dados limpo e concorrência no domínio
- Também ajudou a otimizar o uso de LLMs (OpenAI o1, DeepSeek etc.), reduzindo dependências no código de UI gerado
Arquitetura do app e modelo de dados
-
O SQLite foi usado como armazenamento de dados e adotado no lugar de CoreData por permitir uso imediato de busca full-text (FTS5)
-
Os 3 principais modos/telas do app:
- Importação da biblioteca: salva em massa no banco os caminhos de arquivos de áudio por pasta do iCloud, permitindo busca e gerenciamento flexíveis
- Gerenciamento da biblioteca: playlists, categorização de faixas, edição etc.
- Reprodução musical: gerenciamento da fila (repetição, shuffle etc.) e controles básicos das músicas
-
Fluxo do usuário na importação da biblioteca:
- No estado inicial vazio, o usuário seleciona uma pasta por meio de "Add iCloud Source" e faz a varredura da árvore
- Quando a indexação termina, ele vai para a aba da biblioteca, com listas por palavra-chave e mini player
- Ao adicionar novas músicas, elas são mescladas automaticamente em segundo plano
Camada lógica em estilo backend
- Com base na experiência em startups de web/cloud, a camada lógica e a UI/ViewModel foram separadas de forma rigorosa
- A camada de domínio (Swift actors) concentra a lógica principal de negócio (importação, busca, fila etc.), garantindo thread safety
- As atualizações de UI são divididas de forma limpa via ViewModel, minimizando dependências entre sincronização de arquivos, reprodução e interface, o que melhora a manutenção
Implementando busca full-text com SQLite
- A partir do iOS 11, é possível usar SQLite com suporte a FTS5 sem configuração adicional
- Isso permite busca rápida sem depender de índice externo ou servidor
- A biblioteca SQLite.swift é usada para consultas gerais, enquanto consultas FTS usam SQL escrito diretamente
Estrutura das tabelas FTS
songs_fts: indexa artist, title, album, albumArtist etc. das músicassource_paths_fts: indexa caminhos de arquivos e nomes de arquivos- Elas existem em paralelo às tabelas principais e, na UI, são usadas apenas para busca (READ)
- A atualização do índice é tratada com transações no banco, para manter a consistência dos dados
Busca fuzzy e ranking
- Um wildcard é adicionado automaticamente ao final da entrada, com ordenação por relevância baseada em BM25
- No geral, isso viabiliza uma estrutura de dados previsível, sem dependência de rede, e um poderoso ambiente de busca local
Sistema de arquivos do iOS e uso de bookmarks
- Diferente do macOS, o iOS não oferece suporte a security-scoped bookmarks, o que reduz a persistência no acesso estendido a arquivos externos
- Como apenas a informação do caminho é salva, ao tentar acessar novamente é preciso que o usuário autorize outra vez
- Solução adotada: no momento em que o acesso é permitido, copiar o próprio arquivo para o sandbox do app
- A cópia automática em segundo plano melhora a velocidade de indexação dos arquivos
- Mesmo após reiniciar o dispositivo, ainda é difícil reproduzir diretamente arquivos externos, o que mostra como as restrições de acesso a arquivos no iOS são severas
Reprodução com AVFoundation e design da interface
- O framework AVFoundation e o AVURLAsset são usados para analisar metadados de arquivos de áudio
- Alguns campos, como número da faixa, são interpretados manualmente com base em tags ID3
- Para reprodução de áudio, é usado AVAudioPlayer, e para integração com a Central de Controle são implementados MPRemoteCommandCenter e protocolos Delegate
Impressões após o desenvolvimento e reflexões sobre as políticas da Apple
Pontos incômodos
- Ambiente restritivo do Xcode: o preview em tempo real do SwiftUI evoluiu, mas ainda não alcança a praticidade de VSCode ou Flutter
- Falta de flexibilidade no editor: para usar Swift LSP no Neovim ou VSCode, são necessárias configurações adicionais e a experiência ainda é incompleta
- Algumas partes do SDK ainda são centradas em Objective-C: em áreas como busca de metadados, faltam APIs mais amigáveis ao Swift moderno
- Depuração do iCloud trabalhosa: não é possível implementar completamente recursos de nuvem no preview do SwiftUI, exigindo mocks montados manualmente
Pontos positivos
- Com async/await, escrever código concorrente com I/O-bound ficou consideravelmente mais fácil
- Bibliotecas nativas ricas: foi possível desenvolver recursos mais variados sem ficar preso às limitações de bindings open source
- Design declarativo de UI do SwiftUI: ficou clara a produtividade elevada junto das vantagens do estilo React
Conclusão: desenvolver não deveria ser mais fácil?
- Em 1,5 semana de desenvolvimento, o objetivo de criar um player de música local/offline foi alcançado
- Na prática, porém, há restrições até para distribuir o próprio app: sem certificado de desenvolvedor, ele deixa de funcionar após 7 dias, e é necessário pagar US$ 99 por ano para o registro de desenvolvedor
- Mesmo após o DMA Act da UE, o sideloading ainda não está totalmente liberado, e as restrições continuam para desenvolvedores individuais e amadores
- PWAs também seguem limitados no iOS, com falta de suporte a APIs importantes (Web Bluetooth/USB/NFC, Background Sync etc.)
- A IA reduziu a barreira de desenvolvimento, mas o iOS continua elevando essa barreira por regras artificiais
- As limitações impostas a desenvolvedores independentes e aos direitos do usuário continuam, e o fechamento do iOS segue sendo um obstáculo à inovação
1 comentários
Comentários do Hacker News
asynctraz conveniência na escrita, mas quando a escala cresce, a experiência é de que fica muito mais difícil entender o fluxo do código e a concorrência. Quando há problemas ainda não resolvidos, penso em alternativas como green lightweight threads. Existe a preocupação de que, no longo prazo, uma base em async possa até aumentar o custo de manutenção.