I\'ve been looking through the docs with each beta but haven\'t seen a way to make a traditional paged ScrollView. I\'m not familiar with AppKit so I am wondering if this doesn\
You can simply track state using .onAppear()
to load your next page.
struct YourListView : View {
@ObservedObject var viewModel = YourViewModel()
let numPerPage = 50
var body: some View {
NavigationView {
List(viewModel.items) { item in
NavigationLink(destination: DetailView(item: item)) {
ItemRow(item: item)
.onAppear {
if self.shouldLoadNextPage(currentItem: item) {
self.viewModel.fetchItems(limitPerPage: self.numPerPage)
}
}
}
}
.navigationBarTitle(Text("Items"))
.onAppear {
guard self.viewModel.items.isEmpty else { return }
self.viewModel.fetchItems(limitPerPage: self.numPerPage)
}
}
}
private func shouldLoadNextPage(currentItem item: Item) -> Bool {
let currentIndex = self.viewModel.items.firstIndex(where: { $0.id == item.id } )
let lastIndex = self.viewModel.items.count - 1
let offset = 5 //Load next page when 5 from bottom, adjust to meet needs
return currentIndex == lastIndex - offset
}
}
class YourViewModel: ObservableObject {
@Published private(set) items = [Item]()
// add whatever tracking you need for your paged API like next/previous and count
private(set) var fetching = false
private(set) var next: String?
private(set) var count = 0
func fetchItems(limitPerPage: Int = 30, completion: (([Item]?) -> Void)? = nil) {
// Do your stuff here based on the API rules for paging like determining the URL etc...
if items.count == 0 || items.count < count {
let urlString = next ?? "https://somePagedAPI?limit=/(limitPerPage)"
fetchNextItems(url: urlString, completion: completion)
} else {
completion?(pokemon)
}
}
private func fetchNextItems(url: String, completion: (([Item]?) -> Void)?) {
guard !fetching else { return }
fetching = true
Networking.fetchItems(url: url) { [weak self] (result) in
DispatchQueue.main.async { [weak self] in
self?.fetching = false
switch result {
case .success(let response):
if let count = response.count {
self?.count = count
}
if let newItems = response.results {
self?.items += newItems
}
self?.next = response.next
case .failure(let error):
// Error state tracking not implemented but would go here...
os_log("Error fetching data: %@", error.localizedDescription)
}
}
}
}
}
Modify to fit whatever API you are calling and handle errors based on your app architecture.