Search code examples
scrollviewswiftuihstack

Load more functionality using SwiftUI


i have used ScrollView with HStack, now i need to load more data when user reached scrolling at last.

var items: [Landmark]

i have used array of items which i am appeding in HStack using ForEach

ScrollView(showsHorizontalIndicator: false) {
    HStack(alignment: .top, spacing: 0) {
        ForEach(self.items) { landmark in
            CategoryItem(landmark: landmark)
        }
    }
}

What is the best possible solution to manage load more in SwiftUI without using custom action like loadmore button.


Solution

  • It's better to use ForEach and List for this purpose

    struct ContentView : View {
        @State var textfieldText: String = "String "
        private let chunkSize = 10
        @State var range: Range<Int> = 0..<1
    
        var body: some View {
            List {
                ForEach(range) { number in
                    Text("\(self.textfieldText) \(number)")
                }
                Button(action: loadMore) {
                    Text("Load more")
                }
            }
        }
    
        func loadMore() {
            print("Load more...")
            self.range = 0..<self.range.upperBound + self.chunkSize
        }
    }
    

    In this example each time you press load more it increases range of State property. The same you can do for BindableObject. If you want to do it automatically probably you should read about PullDownButton(I'm not sure if it works for PullUp)

    UPD: As an option you can download new items by using onAppear modifier on the last cell(it is a static button in this example)

    var body: some View {
            List {
                ForEach(range) { number in
                    Text("\(self.textfieldText) \(number)")
                }
                Button(action: loadMore) {
                    Text("")
                    }
                    .onAppear {
                        DispatchQueue.global(qos: .background).asyncAfter(deadline: DispatchTime(uptimeNanoseconds: 10)) {
                            self.loadMore()
                        }
                }
            }
        }
    

    Keep in mind, that dispatch is necessary, because without it you will have an error saying "Updating table view while table view is updating). Possible you may using another async way to update the data