Digamos que você tenha um objeto SwiftData que não permite opcionais:
@Model
class MySet: Identifiable {
var id: UUID
var weight: Int
var reps: Int
var isCompleted: Bool
var exercise: Exercise
Então você obtém dos dados do MySet uma lista desses MySets e os anexa a um estado:
@State var sets: [MySet]
if let newSets = exercise.sets { //unwrapping the passed exercises sets
if (!newSets.isEmpty) { //we passed actual sets in so set them to our set
sets = newSets
}
E você usa essa lista de estados em um ForEach e vincula o Textfield diretamente aos dados assim:
ForEach($sets){ $set in
TextField("\(set.weight)", value: $set.weight, formatter: NumberFormatter())
.keyboardType(.decimalPad)
TextField("\(set.reps)", value: $set.reps,formatter: NumberFormatter())
.keyboardType(.decimalPad)
}
Isso vinculará tudo o que estiver escrito no TextField diretamente ao objeto SwiftData, o que é um problema porque, digamos que você tenha 50 escritos e queira alterá-lo para 60, você precisa limpar o 50 para escrever o 60 e já que o objeto SwiftData não permite nulo, permitirá que você remova o 0, mas não o 5. Existe alguma maneira de remediar isso sem que o objeto swiftData permita opcionais, por exemplo, capturar a limpeza do TextField e torná-lo 0 em vez de nulo quando for limpo?
Tento consertar isso vinculando TextField a um novo estado e usando onChanged:
@State private var reps: Int = 0
@State private var weight: Int = 0
TextField("\(myset.weight)", value: $weight, formatter: NumberFormatter())
.keyboardType(.decimalPad)
.onChange(of: weight) { newWeight in
// Code to run when propertyToWatch changes to newValue
if newWeight != 0 {
myset.weight = newWeight
}
}
mas agora ele está mudando cada repetição e peso de todas as séries quando eu digito uma em vez de apenas aquela em que estou digitando
Você pode criar uma ligação personalizada que deve resolver o problema:
Assim você pode limpar o campo de texto, mas se não inserir um novo valor e parar de editar, ele usará o último valor.
EDITAR:
Se você deseja definir o valor como 0 quando o campo de texto estiver vazio, você precisa alterar o Binding para isto:
Não sei por que seu código não está funcionando. Ajudaria ter um exemplo mínimo reproduzível para trabalhar.
No entanto, uma maneira de chegar a uma solução seria criar um wrapper genérico para um arquivo
TextField
. O wrapper pode conter a variável de estado de sombra e realizar a cópia do opcional para o não opcional.Aqui está uma tentativa de implementar tal wrapper. Eu optei pelo
Textfield
inicializador que levaParseableFormatStyle
:Exemplo de uso: