ScrollViewReader won't scroll the View

224 Views Asked by At

I'm trying to scroll my lazyVStack using scrollViewReader. I've assigned the id to the child view i.e the ChatMessageView the id for the ChatMessageView is the index of my "messages" array which is a published object in ChatManager class. I want the ScrollViewReader to scroll to the last index of the messages array i.e "messages.count - 1".

Currently following is my code:

            ScrollView(.vertical, showsIndicators: false, content:{
                ScrollViewReader { childView in
                    LazyVStack{
                        /// Get all the messages from chat manager with the index of array so you can adjust the position of Textfield according to last message
                        ForEach(chatManager.messages.indices, id: \.self) { index in
                            
                            let msg = chatManager.messages[index]
                            ChatMessageView(message: msg)
                                .id(index)
                        }
                    }//LazyVStack
                    .onAppear(perform: {
                        proxy = childView //The proxy is a state object for the view
                    })
             
                }//ScrollViewReader
            })//ScrollView
        

The function that should scroll the scrollViewReader is the following:

func scrollToBottom(){
        let count = chatManager.messages.count - 1
        proxy?.scrollTo(count, anchor: .bottom)
    }

Instead of count if I pass a hard coded value e.g "10" it will scroll to the 10th index but with count it is not scrolling. I'm calling this function when a user sends or receives a message.

Things I tried:

  • Embedded the ScrollView inside ScrollViewReader
  • checked if the proxy state object is not nil
  • made sure that the ChatMessageView id is of same type as count both are Int.
1

There are 1 best solutions below

3
Ptit Xav On

Add an observer on the message count :

        ScrollView(.vertical, showsIndicators: false, content:{
            ScrollViewReader { childView in
                LazyVStack{
                    /// Get all the messages from chat manager with the index of array so you can adjust the position of Textfield according to last message
                    ForEach(chatManager.messages.indices, id: \.self) { index in
                        
                        let msg = chatManager.messages[index]
                        ChatMessageView(message: msg)
                            .id(index)
                    }
                }//LazyVStack
                // Here : observe changes on chatManager.messages ,
                // assuming messages is a published var
                .onChange(of: chatManager.messages) { newValue in 
                    let count = newValue.count - 1
                    proxy.scrollTo(count, anchor: .bottom)
                })
         
            }//ScrollViewReader
        })//ScrollView