Implementing pull-to-refresh in SwiftUI lists with Combine allows for a seamless user experience when fetching new data. Below is an example of how to achieve this functionality using Swift.
import SwiftUI
import Combine
struct ContentView: View {
@State private var items: [String] = []
@State private var isRefreshing = false
private var cancellable: AnyCancellable?
var body: some View {
List {
ForEach(items, id: \.self) { item in
Text(item)
}
}
.pullToRefresh(isShowing: $isRefreshing) {
fetchData()
}
.onAppear {
fetchData()
}
}
private func fetchData() {
isRefreshing = true
cancellable = Just([1, 2, 3, 4, 5].map { "Item \($0)" })
.delay(for: .seconds(2), scheduler: RunLoop.main)
.sink(receiveCompletion: { _ in
isRefreshing = false
}, receiveValue: { newItems in
items = newItems
})
}
}
extension View {
func pullToRefresh(isShowing: Binding, action: @escaping () -> Void) -> some View {
self.modifier(PullToRefresh(isShowing: isShowing, action: action))
}
}
struct PullToRefresh: ViewModifier {
@Binding var isShowing: Bool
let action: () -> Void
func body(content: Content) -> some View {
content
.background(GeometryReader { geometry in
Color.clear.preference(key: ScrollOffsetKey.self, value: geometry.frame(in: .global).minY)
})
.onPreferenceChange(ScrollOffsetKey.self) { offset in
if offset > 100 && !isShowing {
action()
}
}
}
}
struct ScrollOffsetKey: PreferenceKey {
typealias Value = CGFloat
static var defaultValue: CGFloat = 0
static func reduce(value: inout CGFloat, nextValue: () -> CGFloat) {
value = nextValue()
}
}
How do I avoid rehashing overhead with std::set in multithreaded code?
How do I find elements with custom comparators with std::set for embedded targets?
How do I erase elements while iterating with std::set for embedded targets?
How do I provide stable iteration order with std::unordered_map for large datasets?
How do I reserve capacity ahead of time with std::unordered_map for large datasets?
How do I erase elements while iterating with std::unordered_map in multithreaded code?
How do I provide stable iteration order with std::map for embedded targets?
How do I provide stable iteration order with std::map in multithreaded code?
How do I avoid rehashing overhead with std::map in performance-sensitive code?
How do I merge two containers efficiently with std::map for embedded targets?