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 numOfPeoplemuda, os valores não numéricos são filtrados e o valor filtrado é comparado para ver se numOfPeopledeve ser atualizado uma segunda vez, substituindo a entrada incorreta pela entrada filtrada.
Observe que o Justeditor 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
TextFieldleva um Bindinga umString , quando o conteúdo do campo é alterado, ele também grava essa mudança de volta na @Statevariável.
- Quando uma variável marcada
@State alterada, o SwiftUI recalcula a bodypropriedade da exibição.
- Durante o
bodycálculo, um Justeditor é 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
onReceivemétodo torna um Viewassinante 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
onReceiveassinante 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 @Statevariável, que inicia o loop novamente, mas desta vez o fechamento será executado sem modificar nenhuma propriedade.
Confira Usando Combinar para mais informações.