Embora mostrar um teclado numérico seja uma boa primeira etapa, na verdade não impede que dados ruins sejam inseridos:
- O usuário pode colar texto não numérico no campo de texto
- Os usuários do iPad ainda receberão um teclado completo
- Qualquer pessoa com um teclado Bluetooth conectado pode digitar qualquer coisa
O que você realmente quer fazer é desinfetar a entrada, assim:
import SwiftUI
import Combine
struct StackOverflowTests: View {
@State private var numOfPeople = "0"
var body: some View {
TextField("Total number of people", text: $numOfPeople)
.keyboardType(.numberPad)
.onReceive(Just(numOfPeople)) { newValue in
let filtered = newValue.filter { "0123456789".contains($0) }
if filtered != newValue {
self.numOfPeople = filtered
}
}
}
}
Sempre que numOfPeople
muda, os valores não numéricos são filtrados e o valor filtrado é comparado para ver se numOfPeople
deve ser atualizado uma segunda vez, substituindo a entrada incorreta pela entrada filtrada.
Observe que o Just
editor exige que você import Combine
.
EDITAR:
Para explicar o Just
editor, considere o seguinte esboço conceitual do que ocorre quando você altera o valor em TextField
:
- Porque
TextField
leva um Binding
a umString
, quando o conteúdo do campo é alterado, ele também grava essa mudança de volta na @State
variável.
- Quando uma variável marcada
@State
alterada, o SwiftUI recalcula a body
propriedade da exibição.
- Durante o
body
cálculo, um Just
editor é criado. Combine tem muitos editores diferentes para emitir valores ao longo do tempo, mas oJust
editor obtém "apenas" um valor único (o novo valor de numberOfPeople
) e o emite quando solicitado.
- O
onReceive
método torna um View
assinante um editor, nesse caso, oJust
editor que acabamos de criar. Uma vez inscrito, ele solicita imediatamente quaisquer valores disponíveis ao editor, dos quais existe apenas um, o novo valor de numberOfPeople
.
- Quando o
onReceive
assinante recebe um valor, ele executa o fechamento especificado. Nosso fechamento pode terminar de duas maneiras. Se o texto já é apenas numérico, ele não faz nada. Se o texto filtrado for diferente, ele será gravado na @State
variável, que inicia o loop novamente, mas desta vez o fechamento será executado sem modificar nenhuma propriedade.
Confira Usando Combinar para mais informações.