É didSet no @ficheiro de Ligação específico?

0

Pergunta

Essencialmente, estou de nidificação @Binding 3 camadas de profundidade.

struct LayerOne: View {
    @State private var doubleValue = 0.0
    
    var body: some View {
        LayerTwo(doubleValue: $doubleValue)
    }
}

struct LayerTwo: View {
    @Binding var doubleValue: Double {
        didSet {
            print(doubleValue)
        }
    }
    
    var body: some View {
        LayerThree(doubleValue: $doubleValue)
    }
}

struct LayerThree: View {
    @Binding var doubleValue: Double {
        didSet {
            print(doubleValue) // Only this print gets run when doubleValue is updated from this struct
        }
    }

    var body: Some view {
        // Button here changes doubleValue
    }
}

Qualquer struct eu mudar doubleValue é aquele em que a didSet terá de executar, por exemplo, se eu mudar em LayerThree só que uma impressão, nenhum dos outros.

Eu sou capaz de observar as alterações com .onChange(of: doubleValue) o que será executado quando ele muda, mas não fazendo sentido para mim por isso didSet não conseguir executar, exceto na estrutura onde é alterado a partir de.

É @Binding estrutura específica?

swift swiftui
2021-11-22 18:09:26
3

Melhor resposta

1

Usando a propriedade observadores como didSet em valores envolto em PropertyWrappers não vai ter o "normal" efeito porque o valor está sendo definida dentro da embalagem.

Em SwiftUI, se você deseja acionar uma ação quando um valor for alterado, você deve usar o onChange(of:perform:) modificador.

struct LayerTwo: View {
    @Binding var doubleValue: Double
    
    var body: some View {
        LayerThree(doubleValue: $doubleValue)
          .onChange(of: doubleValue) { newValue 
            print(newValue)
          }
    }
}
2021-11-22 18:26:49

Apanhei-te, então, como eu pensei... ele está sendo definido a partir de dentro da struct que é definir, não através da cadeia.
Joe Scotto
0

Agora, todos trabalhando:

struct ContentView: View {
    
    var body: some View {
        
        LayerOne()
        
    }
    
}


struct LayerOne: View {
    
    @State private var doubleValue:Double = 0.0 {
        didSet {
            print("LayerOne:", doubleValue)
        }
    }
    
    var body: some View {
        LayerTwo(doubleValue: Binding(get: { return doubleValue }, set: { newValue in doubleValue = newValue } ))
    }
    
}

struct LayerTwo: View  {
    
    @Binding var doubleValue: Double {
        didSet {
            print("LayerTwo:", doubleValue)
        }
    }
    
    var body: some View {
        
        LayerThree(doubleValue: Binding(get: { return doubleValue }, set: { newValue in doubleValue = newValue } ))
    }
}




struct LayerThree: View  {
    
    @Binding var doubleValue: Double {
        didSet {
            print("LayerThree:", doubleValue) 
        }
    }
    
    var body: some View {
        
        Text(String(describing: doubleValue))
            
        Button("update value") {
            doubleValue = Double.random(in: 0.0...100.0)
        }
        .padding()
    }
    
}

resultados de impressão:

LayerOne: 64.58963263686678

LayerTwo: 64.58963263686678

LayerThree: 64.58963263686678

2021-11-22 18:20:58

Mas por que você precisa para passar o enlace de que forma? Não deveria didSet obter acionado independentemente de onde a ligação é alterado?
Joe Scotto

Eu acho que não podemos perguntar por que ou como, porque é da Apple e de código fechado. Para fazer didSet começar a trabalhar você precisa de inicialização para o Enlace.
swiftPunk
0

Para ver por que isso acontece, podemos desvendar o açúcar sintático de propriedade wrappers. @Binding var doubleValue: Double traduz-se a:

private var _doubleValue: Binding<Double>
var doubleValue: Double {
    get { _doubleValue.wrappedValue }
    set { _doubleValue.wrappedValue = newValue }
}

init(doubleValue: Binding<Double>) {
    _doubleValue = doubleValue
}

O que você faz em didSet será colocada após a linha _doubleValue.wrappedValue = newValue. Ele deve ser muito óbvia, por que quando você atualizar doubleValue na camada 3, A didSet de doubleValue na camada 2 ou 1 não obter chamado. Eles são simplesmente diferentes propriedades calculadas!

swiftPunk solução funciona através da criação de uma nova ligação cujo enunciador define a estrutura doubleValuedaí chamar didSet:

Binding(get: { return doubleValue }, 
        set: { newValue in doubleValue = newValue }
//                         ^^^^^^^^^^^^^^^^^^^^^^
//                         this will call didSet in the current layer
2021-11-22 18:37:59

Em outros idiomas

Esta página está em outros idiomas

Русский
..................................................................................................................
Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................