SwiftUI 通用下拉刷新视图 [英] SwiftUI Generic Pull to refresh view

查看:19
本文介绍了SwiftUI 通用下拉刷新视图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这个 CustomScrollView,它包装了我的 HomeView,如果你拉下它,它会获取新数据.它工作正常,但问题是我想在多个视图中重用它,我不想为我的每个视图创建一个副本.我试图这样做 var rootView: View 但它抛出一个错误说 View is not convertible to HomeView.

I have this CustomScrollView which wraps my HomeView and if you pull down it fetches new data. It works fine but the thing is that I want to reuse this in multiple views and I do not want to create a copy of this for each of my views. I have tried to do this var rootView: View but it throws an error saying View is not convertible to HomeView.

所以有两件事女巫应该是通用的.HomeView()HomeViewModel.

So there are two thing witch should be generic. HomeView() and HomeViewModel.

知道如何实现这一目标吗?

Any idea how to achieve that?

struct CustomScrollView : UIViewRepresentable {
    var width : CGFloat
    var height : CGFloat

    let viewModel = HomeViewModel()

    func makeCoordinator() -> Coordinator {
        Coordinator(self, homeViewModel: viewModel)
    }

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

        let childView = UIHostingController(rootView: HomeView())

        childView.view.frame = CGRect(x: 0, y: 0, width: width, height: height)

        control.addSubview(childView.view)
        return control
    }

    func updateUIView(_ uiView: UIScrollView, context: Context) { }

    class Coordinator: NSObject {
        var control: CustomScrollView
        var homeViewModel: HomeViewModel
        init(_ control: CustomScrollView, homeViewModel: HomeViewModel) {
            self.control = control
            self.homeViewModel = homeViewModel
        }

        @objc func handleRefreshControl(sender: UIRefreshControl) {
            sender.endRefreshing()
            homeViewModel.loadPackages()
        }
    }
}

推荐答案

这是可能的方法(使用 Xcode 11.4 编译)

Here is possible approach (compiled with Xcode 11.4)

用法:

CustomScrollView(width: 100, height: 100, 
   viewModel: HomeViewMode()) {
      HomeView()
}

通用类型:

protocol CustomViewModel {
    func loadPackages()
}


// It is used generic ViewBuilder pattern for content 
struct CustomScrollView<Content: View, VM: CustomViewModel> : UIViewRepresentable {
    var width : CGFloat
    var height : CGFloat

    let viewModel: VM
    let content: () -> Content

    init(width: CGFloat, height: CGFloat, viewModel: VM, @ViewBuilder content: @escaping () -> Content) {
        self.width = width
        self.height = height
        self.viewModel = viewModel
        self.content = content
    }

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

        let childView = UIHostingController(rootView: content())

        childView.view.frame = CGRect(x: 0, y: 0, width: width, height: height)

        control.addSubview(childView.view)
        return control
    }

    func updateUIView(_ uiView: UIScrollView, context: Context) { }

    class Coordinator: NSObject {
        var control: CustomScrollView<Content, VM>
        var viewModel: VM

        init(_ control: CustomScrollView, viewModel: VM) {
            self.control = control
            self.viewModel = viewModel
        }

        @objc func handleRefreshControl(sender: UIRefreshControl) {
            sender.endRefreshing()
            viewModel.loadPackages()
        }
    }
}

这篇关于SwiftUI 通用下拉刷新视图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆