Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

858
Visualizações
SwiftUI: onChange with @Binding from outside view

Updated to provide full reproducible example.

I have a view MainView with two sub-views, MainTextView and TableOfContentsView. I want to select an item in TableOfContentsView which triggers a scroll position change in MainTextView.

I have an @State var scrollPosition: Int in MainView which is passed to an @Binding var scrollPosition: Int in MainTextView. Here is the code for my 3 views.

struct MainView: View {

    @State private var showingToc = false
    @State private var scrollPosition = 0

    var body: some View {
        
        VStack(alignment: .leading) {
            
            Text("Table of Contents (chapter \(scrollPosition + 1))")
                .onTapGesture {
                    showingToc = !showingToc
                }

            Divider()

            if showingToc {
                TableOfContentsView(
                    onChapterSelected: { chapter in
                        scrollPosition = chapter
                        showingToc = false
                    }
                )
            } else {
                MainTextView(scrollPosition: $scrollPosition)
            }
        }
    }
}
struct TableOfContentsView: View {

    var onChapterSelected: (Int) -> Void
    
    var body: some View {
        ScrollView {
            VStack {
                ForEach(0 ..< 20) { i in
                    Text("Chapter \(i + 1)")
                    .onTapGesture {
                        onChapterSelected(i)
                    }
                }
            }
        }
    }
}
struct MainTextView: View {
    
    let lorumIpsum = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."

    @Binding var scrollPosition: Int
    @State private var scrollProxy: ScrollViewProxy? = nil

    var body: some View {
        ScrollView {
            ScrollViewReader { proxy in
                
                VStack(alignment: .leading) {
                    ForEach(0 ..< 20) { i in
                        VStack(alignment: .leading) {
                            
                            Text("Chapter \(i + 1)")
                                .frame(maxWidth: .infinity, alignment: .center)
                                .padding(.top)

                            Text(lorumIpsum)
                                .font(.system(size: 18, design: .serif))
                                .padding(.top)
                        }
                        .padding(.bottom, 20)
                        .id(i)
                    }
                }
                .padding(.leading)
                .padding(.trailing)
                .onAppear {
                    scrollProxy = proxy
                }
            }
        }
        .onChange(of: scrollPosition) { target in
            scrollProxy?.scrollTo(target, anchor: .top)
        }
    }
}

My .onChange function is never called - if I place a breakpoint inside, it never hits the breakpoint. What am I missing here? How do I observe an @Binding that is changed from outside of the view?

over 4 years ago · Santiago Trujillo
1 Respostas
Responde à pergunta

0

.onChange is not going to get called cause MainTextView doesn't exist when showingToc = true because of the conditional block:

if showingToc {
  TableOfContentsView(onChapterSelected: { chapter in
      scrollPosition = chapter
      showingToc = false
    }
  )
} else {
  MainTextView(scrollPosition: $scrollPosition)
}

You might want to consider showing TOC as an overlay. But to get your current code working, you need to call proxy.scrollTo in your .onAppear of MainTextView:

.onAppear {
  scrollProxy = proxy
  scrollProxy?.scrollTo(scrollPosition, anchor: .top)
}
over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda