Search code examples
swiftuirefreshpull-to-refresh

Introspect library UIRefreshControl with SwiftUI not working


I am trying to use the Introspect library to refresh a list control in SwiftUI when a pulldown occurs.

My List modifier is as follows:

.introspectTableView (tableView in {    
    tableView.refreshControl = UIRefreshControl()
    // code here to get new data
    tableView.refreshControl?.endRefreshing()
}

The code to get new data keeps executing.

Any help would be appreciated.


Solution

  • The introspectTableView closure is being called every time the view is refreshed, which is why the code to get new data keeps being executed.

    To solve this, what you need to is to call your refreshing code only when the user has been pulled. The only way I could do this was by creating a RefreshHelper class, since the UIRefreshControl still depends on @objc functions and Selectors.

    Here's a sample that roughly implements what you want:

    struct ContentView: View {
        @State var data: [String] = (0...5).map { "Item \($0)" }
        let refreshHelper = RefreshHelper()
    
        class RefreshHelper {
            var parent: ContentView?
            var refreshControl: UIRefreshControl?
    
            @objc func didRefresh() {
                guard let parent = parent, let refreshControl = refreshControl else { return }
                parent.data.append("Item \(parent.data.count)") // load data here
                refreshControl.endRefreshing()
            }
        }
    
        var body: some View {
            List(data, id: \.self) { i in
                Text("Item \(i)")
            }
            .introspectTableView { tableView in
                let control = UIRefreshControl()
    
                refreshHelper.parent = self
                refreshHelper.refreshControl = control
    
                control.addTarget(refreshHelper, action: #selector(RefreshHelper.didRefresh), for: .valueChanged)
                tableView.refreshControl = control
            }
        }
    }