Pular para o conteúdo
Development

Uma rejeição da App Store, uma pegadinha do MusicKit, e um trabalho que eu achei que tinha perdido

Por Victor Da Luz
iosswiftmusickitapp-storedev-logdeep-cut-atlas

O Deep Cut Atlas recebeu sua primeira rejeição da App Store essa semana, e isso virou uma lição em duas partes: uma sobre a superfície de API do MusicKit, e outra sobre a minha própria higiene de git.

A rejeição

O revisor da Apple encontrou dois bugs. Primeiro, tanto History quanto Discover mostravam a string bruta “Privacy acknowledgement required” em vez de qualquer interface real. Segundo, tocar em “Enable lifetime Pro” em Configurações disparava um alerta de erro.

A causa raiz do primeiro bug é uma distinção sobre a qual eu não tinha pensado o suficiente: o status de autorização do MusicKit só diz se o usuário concedeu ao seu app permissão para acessar a biblioteca dele. Não diz nada sobre se a conta dele de fato tem uma assinatura ativa do Apple Music. Meu app travava a checagem na autorização e parava por aí, então um revisor que concedeu acesso mas não tinha assinatura passava direto pela barreira e batia num erro bruto do MusicKit logo na próxima requisição. A correção é uma segunda checagem, separada, via MusicSubscription.current, com sua própria tela dedicada em vez de três abas cada uma exibindo sua própria versão do mesmo problema de fundo.

O segundo bug era mais simples: o botão de desbloqueio Pro continuava tocável mesmo quando o produto da compra dentro do app ainda não tinha carregado, então um produto nil significava um alerta de erro inevitável ao tocar. Correção direta: esconder o botão até o produto de fato estar lá.

Acertando o tipo de erro certo

O texto de erro específico que o revisor da Apple viu (“Privacy acknowledgement required”) vem de um caso de erro real do Swift, mas tentar adivinhar o tipo exato de memória foi uma má ideia. Eu estava bastante confiante de que ele estava em MusicSubscription.Error, que na verdade não é um tipo real, ou pelo menos não um que eu conseguisse encontrar documentado. Algumas buscas depois, confirmei que o tipo real é MusicTokenRequestError.privacyAcknowledgementRequired. Valeu os cinco minutos extras: lançar uma cláusula catch que casa com um caso que não existe significa que ela nunca dispara, silenciosamente, e você não corrigiu nada.

A parte em que achei que o trabalho tinha sumido

Essa é a parte da qual estou menos orgulhoso. Uma sessão de trabalho anterior aparentemente já tinha construído essa correção exata, “complete, simulator-verified,” deixada como uma nota não commitada no ticket de acompanhamento. Quando fui retomar o trabalho, dei grep no código inteiro e em todas as branches procurando as classes que aquele comentário descrevia. Nada. Concluí que o trabalho tinha se perdido, mudanças não commitadas que nunca foram salvas antes de uma troca de branch, e reconstruí tudo a partir das anotações do ticket.

Não tinha se perdido. Estava parado no git stash, que eu nem cogitei checar. Um stash não aparece no git branch, não aparece no git log, e um grep na árvore de trabalho também não o enxerga, então minha busca tinha um ponto cego de verdade que eu nem sabia que existia, até esbarrar nele mais tarde, fazendo uma limpeza de branches sem relação nenhuma.

O lado bom: comparando as duas versões, minha reconstrução pegou um bug real que a original tinha, aquele tipo MusicSubscription.Error errado. Então o trabalho redundante não foi desperdiçado. Mas “irrecuperável” foi uma afirmação que eu fiz com mais confiança do que eu realmente tinha conquistado, e quero lembrar disso da próxima vez que algo parecer perdido.

O que vem a seguir

A correção no código está pronta, testada, e mesclada. O que falta é inteiramente comigo: confirmar no App Store Connect que a compra dentro do app está de fato anexada ao envio da versão (provavelmente todo o segundo bug), depois incrementar o build e reenviar.

Leitura relacionada

Você também pode achar útil

NordPass

NordPass

Gerenciador de senhas da equipe por trás da NordVPN, com um plano gratuito.

Como afiliado da NordPass, ganho com compras qualificadas.

Saiba mais
AdGuard

AdGuard para iOS

Bloqueio de anúncios e rastreadores em todo o sistema no iOS, sem necessidade de um servidor DNS separado.

Como afiliado da AdGuard, ganho com compras qualificadas.

Saiba mais
Proton

Proton Drive

Armazenamento em nuvem criptografado, da equipe por trás do Proton Mail.

Como parceiro da Proton, ganho com compras qualificadas dos serviços de privacidade e segurança da Proton (Pass, Mail, VPN, Drive).

Saiba mais