Os botões não estavam quebrados: a main thread estava ocupada
118 testes verdes, uma passada limpa no simulador, e botões mortos num telefone de verdade. O bug era um serviço @MainActor fazendo trabalho síncrono entre awaits.
118 testes verdes, uma passada limpa no simulador, e botões mortos num telefone de verdade. O bug era um serviço @MainActor fazendo trabalho síncrono entre awaits.
@MainActor elimina data races, não races de interleaving. Um token de geração, uma guarda contra falha desatualizada, e um teste de race determinístico sem sleeps.
Todo branch de catch era código morto nos testes. Uma costura de falha de 15 linhas resolveu isso, e depois uma suíte de testes sem anotação derrubou o runner inteiro.
Cinco fatias de ~700 linhas, briefings que também perguntam o que está bem feito, e a etapa de verificação que separou bugs reais dos só plausíveis.
Adotando um linter em um código que nunca teve um, um hook de pre-commit sem framework, e três coisas que o runner macOS fez que a documentação não mencionava.
A API de compra é a parte fácil. As junções entre StoreKit 2, isolamento do Swift 6 e observação do SwiftUI foram onde o tempo foi.
Um mini-player inline para quando o playback do MusicKit fica mudo no simulador: um protocolo de dois métodos, um indicador que mente de forma honesta, e um bug deixado de propósito.
Cinco testes reportando um «Crash» genérico: um helper bem-intencionado deixou o ModelContainer ser desalocado enquanto o store manteve seu context. Um context é algo emprestado.
O checker de isolamento baseado em regiões manda eu abrir um bug, e a Task não estruturada, hoje fora de moda, acaba sendo a ferramenta certa.
Construindo o fluxo de adicionar à biblioteca e aprendendo que as cópias de biblioteca e de catálogo do MusicKit para um mesmo álbum são objetos sem relação nenhuma, no que diz respeito aos IDs.
Página 3 de 4