Skip to content
This repository has been archived by the owner on Oct 24, 2024. It is now read-only.

Latest commit

 

History

History
95 lines (78 loc) · 2.52 KB

README.md

File metadata and controls

95 lines (78 loc) · 2.52 KB

RefreshableScrollView

This project is no longer in use. Wrapping SwiftUI views in UIKit views, and embedding them again in SwiftUI is a significant source of bugs. Be warned!

In SwiftUI, it is currently only possible to use pull to refresh on List views. This package provides a custom scroll view that is refreshable, so that you can pull to refresh any SwiftUI view you desire. It responds to the .refreshable() modifier, so you use it in the exact same way as you would refresh a List.

It also supports passing in a custom UIRefreshControl, so that you may have loaders with a custom look.

demo

How does it work?

This view works by wrapping UIScrollView internally and putting your SwiftUI view in a UIHostingController within the scroll view.

Examples

A full sample project with various refreshable views is available at: https://github.com/Q42/RefreshableScrollViewDemo

Basic example

struct CustomView: View {
  var body: some View {
    RefreshableScrollView {
      Text("Hello, World!")
    }
    .refreshable {
      do {
        // Sleep for 2 seconds
        try await Task.sleep(nanoseconds: 2 * 1_000_000_000)
      } catch {}
    }
  }
}

Lazy VStack

struct StackView: View {
  struct Item: Identifiable {
    let id: Int
  }
  @State var items: [Item] = Array(1...100).map(Item.init)
  @State var count = 100

  var body: some View {
    RefreshableScrollView {
      LazyVStack(alignment: .leading) {
        ForEach(items) { item in
          Text("Row \(item.id)")
        }
      }
    }
    .refreshable {
      do {
        // Sleep for 2 seconds
        try await Task.sleep(nanoseconds: 2 * 1_000_000_000)
      } catch {}
      
      count += 1
      items.insert(Item(id: count), at: 0)
    }
  }
}

Lazy VGrid

struct GridView: View {
  let columns: [GridItem] = Array(repeating: .init(.flexible()), count: 2)

  var body: some View {
    RefreshableScrollView {
      LazyVGrid(columns: columns) {
        ForEach((0...79), id: \.self) {
          let codepoint = $0 + 0x1f600
          let codepointString = String(format: "%02X", codepoint)
          Text("\(codepointString)")
          let emoji = String(Character(UnicodeScalar(codepoint)!))
          Text("\(emoji)")
        }
      }.font(.largeTitle)
    }
    .refreshable {
      do {
        // Sleep for 2 seconds
        try await Task.sleep(nanoseconds: 2 * 1_000_000_000)
      } catch {}
    }
  }
}