Search code examples
swiftuiscrollview

ScrollTo in ScrollView not working as expected


Basic scrollView . When using value for scrollView.scrollTo(value,anchor:.bottom) , it scrolls . When replacing by its value "99" , it doesn t . NOt sure if this is intended or not .If not, would like to know how to use the value of the id instead of retrieving it frol the position of the element .

struct Testchat: View {
    @State private var listMessages: [MessageTest] = []
    @State private var scrolled = false

    var body: some View {
        ScrollViewReader { scrollView in
            ScrollView {
                VStack(spacing: 0) {
                    ForEach(listMessages, id: \.id) { messageInList in
                        Text(messageInList.id)
                            .onAppear {
                                if !scrolled {
                                    let value = listMessages[99].id
                                    scrollView.scrollTo("99",anchor: .bottom)
                                    scrolled = true
                                }
                            }
                    }
                }
            }
        }
        .onAppear {
            for i in 0 ..< 100 {
                let messagetest:MessageTest = .init()
                messagetest.id = i.description
                messagetest.message = i.description
                listMessages.append(messagetest)
            }
        }
    }
}
public class MessageTest: NSObject, Codable, ObservableObject {
    var message: String!
    var id: String!

    public override init() {
        message = "VOID"
        id = "VOID"
    }
}

Solution

  • In your ForEach, your are identifying each row by the \.id key-path. The id property in MessageTest is an optional, of type String! (but is really a String? to mean Optional<String>).

    Because of this, you need to pass in the row to scroll to as a String? type, rather than just String.

    Change the line to the following, by adding the cast:

    scrollView.scrollTo("99" as String?, anchor: .bottom)
    

    Link here to an answer about how String? and String! are both Optional<String>, but the ! version is just implicitly force-unwrapped.