Por que uma leitura falha com um erro de tag perdida?
Porque a tag saiu do campo antes de a troca terminar, o que uma mão faz em meio segundo. O Android levanta TagLostException em qualquer operação que toque o rádio, o iOS falha com um erro de conexão perdida, e uma gravação interrompida assim deixa um resultado que ninguém conhece ainda.
O que cada plataforma levanta
No Android toda operação que toca o rádio consegue levantar isso. A referência do TagLostException faz dele uma subclasse de IOException, e connect(), transceive(), readPages() e writePage() o declaram todos. Um erro diferente quer dizer um problema diferente: reusar um objeto Tag depois de a tag dele ter ido embora levanta SecurityException, já que esse objeto pertencia a uma única aparição.
No iOS o mesmo evento chega como um código de erro. readerTransceiveErrorTagConnectionLost diz que o leitor perdeu a conexão com a tag, e os vizinhos dele nomeiam os outros casos: readerTransceiveErrorTagNotConnected quando a tag não está no estado conectado, readerTransceiveErrorSessionInvalidated quando a sessão terminou por baixo dela, readerTransceiveErrorRetryExceeded quando houve tentativas demais.
A mão primeiro, o código depois
As causas físicas vêm primeiro porque são as frequentes. Uma gravação demora mais que uma leitura, então um gesto que lê de modo confiável pode ser breve demais para gravar, o que a página da gravação pela metade descreve do lado do usuário. Uma capa grossa, uma tag pequena ou um ângulo desajeitado não deixam margem, e a tag sai do alcance com um milímetro de movimento.
As causas do código são mais sutis. Todo comando é uma ida e volta, então uma sequência de vinte deixa vinte chances de perder a tag, e o trabalho feito entre dois comandos, uma conta ou pior uma chamada de rede, segura a tag aberta à toa. Abrir outra classe de tecnologia no meio da sequência pode fazer a plataforma selecionar a tag de novo, o que a página da autenticação cobre onde isso custa mais.
O que fazer com a tag que você perdeu
Trate uma tag perdida durante uma gravação como um resultado desconhecido em vez de uma falha. O comando pode ter chegado à tag antes de a resposta se perder, então o passo seguinte é ler a memória de volta, e não gravar de novo, e uma ordem que não deixa nada meio válido torna isso legível: a página das gravações interrompidas a expõe.
Depois comece do princípio. A tag que volta é uma detecção nova, um objeto Tag novo no Android e uma detecção nova no iOS, qualquer autenticação se foi, e uma sequência não dá para retomar pelo meio. O código que guarda estado por cima de uma perda tem de reconciliá-lo com o que ele lê de volta.
Deixar a janela larga o bastante
Encurte a troca em vez de alongar o tempo de espera. Leia nos maiores blocos que o protocolo oferece, mantenha baixo o número de comandos, e faça antes do toque tudo o que não precisa da tag, a conta que a página dos tempos de espera torna explícita.
Depois projete a interface para uma mão. Diga ao usuário quando afastar, mostre a conclusão só quando a chamada tiver retornado, e teste com a tag na mão em vez de testar com o celular deitado numa mesa, onde a janela nunca se fecha e o defeito nunca aparece.
Perguntas frequentes
Um erro de tag perdida quer dizer uma tag quebrada?
Quase nunca. Ele quer dizer que a tag saiu do campo no meio da troca. A mesma tag em geral lê na tentativa seguinte se o celular ficar parado.
Dá para retomar uma troca depois de a tag voltar?
Não. A tag que volta é uma detecção nova, e qualquer autenticação se foi. Comece pela detecção, e leia de volta antes de gravar outra vez.
Por que uma gravação falha mais que uma leitura?
Ela demora mais, então precisa de um apoio mais longo. Um gesto que lê de modo confiável é regularmente breve demais para gravar.
O que SecurityException está fazendo aqui?
Ele quer dizer que o código reusou um objeto Tag de uma aparição anterior. Cada detecção dá um objeto novo, e só o mais recente funciona.