Pull down to refresh data in SwiftUI

2020-05-14 04:09发布

i have used simple listing of data using List. I would like to add pull down to refresh functionality but i am not sure which is the best possible approach.

Pull down to refresh view will only be visible when user tries to pull down from the very first index same like we did in UITableView with UIRefreshControl in UIKit

Here is simple code for listing data in SwiftUI.

struct CategoryHome: View {
    var categories: [String: [Landmark]] {
        .init(
            grouping: landmarkData,
            by: { $0.category.rawValue }
        )
    }

    var body: some View {
        NavigationView {
            List {
                ForEach(categories.keys.sorted().identified(by: \.self)) { key in
                    Text(key)
                }
            }
            .navigationBarTitle(Text("Featured"))
        }
    }
}

4条回答
ゆ 、 Hurt°
2楼-- · 2020-05-14 04:35

The swiftui-introspects has not supported on masOS yet, so if you are going to build a UI that works for both iOS and macOS, consider the Samu Andras library.

I forked his code, added a few enhancements, and added the ability to use without the NavigationView

Here is the sample code.

RefreshableList(showRefreshView: $showRefreshView, action:{
                           // Your refresh action
                            // Remember to set the showRefreshView to false
                            self.showRefreshView = false

                        }){
                            ForEach(self.numbers, id: \.self){ number in
                                VStack(alignment: .leading){
                                    Text("\(number)")
                                    Divider()
                                }
                            }
                        }

For more details, you can visit the link below. https://github.com/phuhuynh2411/SwiftUI-PullToRefresh

查看更多
男人必须洒脱
3楼-- · 2020-05-14 04:47

Hi check out this library I made: https://github.com/AppPear/SwiftUI-PullToRefresh

You can implement it by one line of code:

struct CategoryHome: View {
    var categories: [String: [Landmark]] {
        .init(
            grouping: landmarkData,
            by: { $0.category.rawValue }
        )
    }

    var body: some View {
        RefreshableNavigationView(title: "Featured", action:{
           // your refresh action
        }){
                ForEach(categories.keys.sorted().identified(by: \.self)) { key in
                    Text(key)
                    Divider() // !!! this is important to add cell separation
                }
            }
        }
    }
}
查看更多
劳资没心,怎么记你
4楼-- · 2020-05-14 04:52

I needed the same thing for an app I'm playing around with, and it looks like the SwiftUI API does not include a refresh control capability for ScrollViews at this time.

Over time, the API will develop and rectify these sorts of situations, but the general fallback for missing functionality in SwiftUI will always be implementing a struct that implements UIViewRepresentable. Here's a quick and dirty one for UIScrollView with a refresh control.

struct LegacyScrollView : UIViewRepresentable {
    // any data state, if needed

    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }

    func makeUIView(context: Context) -> UIScrollView {
        let control = UIScrollView()
        control.refreshControl = UIRefreshControl()
        control.refreshControl?.addTarget(context.coordinator, action:
            #selector(Coordinator.handleRefreshControl),
                                          for: .valueChanged)

        // Simply to give some content to see in the app
        let label = UILabel(frame: CGRect(x: 0, y: 0, width: 200, height: 30))
        label.text = "Scroll View Content"
        control.addSubview(label)

        return control
    }


    func updateUIView(_ uiView: UIScrollView, context: Context) {
        // code to update scroll view from view state, if needed
    }

    class Coordinator: NSObject {
        var control: LegacyScrollView

        init(_ control: LegacyScrollView) {
            self.control = control
        }

        @objc func handleRefreshControl(sender: UIRefreshControl) {
            // handle the refresh event

            sender.endRefreshing()
        }
    }
}

But of course, you can't use any SwiftUI components in your scroll view without wrapping them in a UIHostingController and dropping them in makeUIView, rather than putting them in a LegacyScrollView() { // views here }.

查看更多
叼着烟拽天下
5楼-- · 2020-05-14 04:52

Here's an implementation that introspects the view hierarchy and adds a proper UIRefreshControl to a SwiftUI List's table view: https://github.com/timbersoftware/SwiftUIRefresh

Bulk of the introspection logic can be found here: https://github.com/timbersoftware/SwiftUIRefresh/blob/15d9deed3fec66e2c0f6fd1fd4fe966142a891db/Sources/PullToRefresh.swift#L39-L73

查看更多
登录 后发表回答