I want to use ScrollView and ForEach to show elements in the list of Post
.
Every time when the scrollbar reach to the top of the ScrollView, i'm gonna try to query more Posts and update the list.
When i use PullToRefresh
and getPostsBeforeIndex()
to insert previous Posts to the List, I want the ScrollView to not only update the views of new Post inside of the ScrollView, but also keep the relative scrollbar position unchanged and still showing the view of previous top Post view.(just update the scrollview content but not to change the current scrollbar position)
ScrollView of Post list:
ScrollViewReader { proxy1 in
ScrollView {
PullToRefresh(coordinateSpaceName: "pullToRefresh") {
userPostViewModel.getPostsBeforeIndex()
}
ForEach(userPostViewModel.postListSinceIndex) { post in
VStack {
PostView(post: post, muted: $muted)
.padding(.bottom, 23)
}
}
.offset(y: -2)
.padding(.top, 2)
.background(Color.white)
}
.coordinateSpace(name: "pullToRefresh")
.onAppear(){
if(first) {
first = false
userPostViewModel.getPostsSinceIndex()
}
}
}
userPostViewModel:
class UserPostViewModel: ObservableObject {
@Published var postList = [Post]()
@Published var isLoadingPage = false
@Published var canLoadMore = true
@Published var canLoadMoreUp = true
private var lastLoad = 0
private var step = 3
let userID: String
@Published var postListSinceIndex = [Post]()
private var lastLoadIndex = 0
private var firstLoadIndex = 0
init(id: String, postIndex: Int) {
self.userID = id
self.lastLoadIndex = postIndex
self.firstLoadIndex = postIndex
}
func getPostsBeforeIndex() {
guard !isLoadingPage && canLoadMoreUp else {
return
}
isLoadingPage = true
let query = PFQuery(className:"Post")
query.whereKey("user", equalTo: userID)
query.order(byDescending: "createdAt")
if(self.firstLoadIndex >= step) {
query.limit = step
query.skip = self.firstLoadIndex - step
} else {
query.limit = self.firstLoadIndex
query.skip = 0
}
query.findObjectsInBackground { (objects: [PFObject]?, error: Error?) in
if let error = error {
print("Failed getting user's posts from parse server")
print(error.localizedDescription)
} else if let objects = objects {
DispatchQueue.main.async {
if(objects.count < self.step) {
self.canLoadMoreUp = false
}
for i in 0..<objects.count {
self.postListSinceIndex.insert(PostViewModel.parsePost(d: objects[objects.count - 1 - i]), at: 0)
}
self.firstLoadIndex = self.firstLoadIndex - objects.count
self.isLoadingPage = false
}
}
}
}
}
I've tried to use proxy1.scrollTo() but it didn't work.