0
import Foundation
import SwiftUI

struct TestChatUIView: View {
    @State var models: [TestChatModel2] = []
    
    init() {

    }
    var body: some View {
        ZStack(alignment: .top) {
            ScrollViewReader { scrollViewProxy in
                ScrollView {
                    LazyVStack(spacing: 0) {
                        ForEach(models.indices, id: \.self) { index in
                            VStack {
                                let message = models[index]
                                Text("\(message.id)")
                                    .id(message.id)
                                    .flipped()
                                    .frame(minHeight: 40)
                                    .onAppear {
                                        if index < (3) {
                                            
                                            for i in 0...20 {
                                                let newModel = TestChatModel2(id: "id \(models.count + 1)", date: Date())
                                                models.insert(newModel, at: 0)
                                            }
                                        }
                                    }
                            }
                        }
                        
                    }
                }
                .flipped()
                    
            }
            
            VStack {
                Spacer()
                Button {
                    for int in 0...30 {
                        models.insert(.init(id: "id \(models.count + 1)", date: Date()), at: 0)
                    }
                } label: {
                    Text("loadMore")
                        .background(Color.red)
                }

            }
        }
    }
}

struct TestChatModel2: Identifiable {
    var id: String = UUID().uuidString
    var date: Date
}
extension View {
    
    func flipped() -> some View {
        self.rotationEffect(.radians(Double.pi))
            .scaleEffect(x: -1, y: 1, anchor: .center)
    }
}

I am making chatting system, this code is kinda very sample of it. What I want to is load more messages when it gets close to bottom. But problem is scroll focus keeps locating bottom so it cause recursive loadmore function.

How to fix?

I changed .flipped() modifier's location like on VStack, ForEach, but it never works.

2

1 Answer 1

0

I debugged a lot and just figure out that is not feasible. Even i made a same logic using UIKit (ScrollView+StackView and TableView, CollectionView), all the same issue happened(when some items are added on top, scroll moved to still top)

Also some chat app such as sendbird also could not resolve this error

import Foundation
import SwiftUI

struct TestChatUIView: View {
    @State var models: [TestChatModel2] = []
    @State var modelId: String?
    
    var body: some View {
        ZStack(alignment: .top) {
            ScrollViewReader { scrollViewProxy in
                ScrollView {
                    LazyVStack(spacing: 0) {
                        ForEach(models, id: \.id) { message in
                            Text("\(message.id)")
                                .flipped()
                                .frame(minHeight: 40)
                        }
                    }
                    .scrollTargetLayout()
                }
                .scrollPosition(id: $modelId)
                .flipped()
                VStack {
                    
                    HStack {
                        Button("Prepend") {
                            loadPrev()
                            
                        }
                        Button("Movee") {
                            scrollViewProxy.scrollTo("id 31", anchor: .center)
                        }
                        Button("Append") {
                            loadMore()
                        }
                    }
                    
                }
                
            }
            .onAppear(perform: {
                for int in 0...30 {
                    models.insert(.init(id: "id \(models.count + 1)", date: Date()), at: 0)
                }
            })
        }
    }
    
    func loadMore() {
        for i in 0...20 {
            let newModel = TestChatModel2(id: "id \(models.count + 1)", date: Date())
            models.insert(newModel, at: 0)
        }
    }
    
    func loadPrev() {
        for i in 0...20 {
            let newModel = TestChatModel2(id: "- id \(models.count + 1)", date: Date())
            models.append(newModel)
        }
    }
}

struct TestChatModel2: Identifiable, Equatable {
    var id: String = UUID().uuidString
    var date: Date
}

extension View {
    
    func flipped() -> some View {
        self.rotationEffect(.radians(Double.pi))
            .scaleEffect(x: -1, y: 1, anchor: .center)
    }
}

However above the codes, i added.

.scrollTargetLayout() .scrollPosition(id: $modelId)

it works for me (Sadly my app target is iOS15). and those func available after iOS17

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.