Como gravar e bloquear uma tag NDEF a partir de um aplicativo iOS?
Abra uma sessão NDEF que não termina na primeira leitura, conecte-se à tag que o delegado recebe, e confira o estado e a capacidade dela antes de gravar a mensagem inteira numa chamada só. writeLock torna a tag somente leitura de vez. Tudo acontece dentro de uma sessão, então o usuário segura o celular até o aplicativo dizer que terminou.
Uma sessão que fica aberta
A gravação acontece dentro de uma sessão de leitura, então a sessão não pode terminar na primeira leitura. A observação da Apple sobre o inicializador diz para passar false em invalidateAfterFirstRead numa sessão que grava, o que a mantém ativa até o aplicativo terminar.
O delegado implementa readerSession(_:didDetect:), disponível a partir do iOS 13, para receber objetos NFCNDEFTag em vez de mensagens, e depois chama connect(to:) naquele que ele quer. Uma tag fica conectada até o aplicativo se conectar a outra ou voltar a sondar.
Duas tags no campo são um caso real. O exemplo de leitor de tags da Apple conta as tags antes de gravar, pede ao usuário por alertMessage que tire todas elas, e volta a sondar depois de um instante em vez de gravar na tag errada.
Estado e capacidade primeiro
queryNDEFStatus devolve dois valores que decidem se dá para seguir: um estado, notSupported, readOnly ou readWrite, e a capacidade, a maior mensagem NDEF que a tag consegue guardar, em bytes.
Compare a capacidade com a mensagem antes de gravar. Uma mensagem que não cabe falha com ndefReaderSessionErrorTagSizeTooSmall, depois que o usuário segurou o celular parado à toa.
A gravação
writeNDEF(_:) salva a mensagem inteira numa chamada só e informa ao manipulador de conclusão dela, ou lança na forma assíncrona. A referência dela a amarra ao estado: grave só quando queryNDEFStatus devolveu readWrite.
Os erros dizem qual etapa falhou: ndefReaderSessionErrorTagNotWritable para uma tag somente leitura, ndefReaderSessionErrorTagSizeTooSmall para uma mensagem longa demais, ndefReaderSessionErrorTagUpdateFailure para uma atualização que não terminou, e readerTransceiveErrorTagConnectionLost quando a tag saiu do campo.
Depois de uma atualização que falhou ou de uma ligação perdida, leia a tag de novo antes de tentar outra vez. A gravação pode ter parado no meio, o caso que a página da gravação interrompida cobre do lado do usuário.
Quando a gravação dá certo, diga isso na folha e termine a sessão com invalidate(). Até lá, o usuário não sabe que o celular pode ser afastado.
Bloquear é permanente
writeLock() muda o estado da tag para somente leitura. A documentação dela explica que ela atualiza o byte de condição de acesso em gravação no controle de arquivo NDEF da tag, e a chama de uma ação permanente que não pode ser desfeita.
Mantenha-a como uma ação separada da gravação, feita depois que o conteúdo foi lido de volta e conferido na outra plataforma. Se vale bloquear está coberto na página do bloqueio.
O que as chamadas NDEF não fazem
As chamadas NDEF param na mensagem. Uma senha, um contador ou uma página de configuração são comandos de chip, alcançados por uma sessão de tag e pelo protocolo da própria tag, como sendMiFareCommand numa tag MIFARE, com os comandos tirados da ficha técnica do chip.
Esse trabalho sai inteiramente da sessão NDEF, e é por isso que a escolha da sessão vem primeiro, na página das sessões.
Perguntas frequentes
Por que a minha gravação falha com ndefReaderSessionErrorTagSizeTooSmall?
A mensagem é maior do que a tag consegue guardar. queryNDEFStatus devolve a capacidade em bytes, então compare as duas antes de gravar.
Uma tag bloqueada pode ser desbloqueada pelo iOS?
Não. A Apple descreve writeLock como uma ação permanente que não pode ser desfeita.
Um aplicativo de iPhone consegue pôr uma senha numa tag?
Não com as chamadas NDEF. Uma senha é posta com comandos de chip, enviados numa sessão de tag pelo protocolo da tag, com os comandos tirados da ficha técnica do chip.
Por que a sessão tem de ficar aberta depois da leitura?
A gravação acontece dentro dela. Com invalidateAfterFirstRead em true, a sessão termina depois da primeira leitura e não deixa nada com que gravar.