首页 > 解决方案 > 检测滚动视图底部时的 UIScrollView 故障

问题描述

我有这个自定义视图,它在 SwiftUI 中创建了一个滚动视图。我正在尝试检测视图的底部,以便我可以调用我的load()函数来加载下一批数据。问题是:

我的实现检测底部,不是在我到达底部时而是在:我到达底部并且我拉起屏幕时,所以我需要比底部多得多才能触发它。当滚动条位于底部时,没有任何反应。

更奇怪的是,即使只有一个项目,当我拉起(甚至认为没有滚动条)时,load()也会再次被调用。

此外,它也与我的handleRefreshControl(sender: UIRefreshControl). 当我拉起屏幕时,这也会被触发。这应该仅在向下滚动而不是向上滚动时触发。

我不希望此时调用我的函数。

在此处输入图像描述

但在这一点上。因此,当滚动条位于末尾时(甚至在末尾之前一点点)。

在此处输入图像描述

我在这里做错了什么?

import SwiftUI

struct CustomScrollView<Content: View, VM: LoadProtocol> : UIViewRepresentable {
    var width : CGFloat
    var height : CGFloat
    
    var viewModel: VM
    let content: () -> Content
    
    func makeCoordinator() -> Coordinator {
        Coordinator(self, viewModel: viewModel)
    }
    
    func makeUIView(context: Context) -> UIScrollView {
        let control = UIScrollView()
        control.refreshControl = UIRefreshControl()
        control.refreshControl?.addTarget(context.coordinator, action: #selector(Coordinator.handleRefreshControl), for: .valueChanged)
        
        control.delegate = context.coordinator
        
        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, UIScrollViewDelegate {
        var control: CustomScrollView<Content, VM>
        var viewModel: VM
        init(_ control: CustomScrollView, viewModel: VM) {
            self.control = control
            self.viewModel = viewModel
        }
        
        var fetchingMore = false
        
        func scrollViewDidScroll(_ scrollView: UIScrollView) {
            if (scrollView.contentOffset.y + 1) >= (scrollView.contentSize.height - scrollView.frame.size.height) {
                if !fetchingMore {
                    beginFetchMore()
                }
            }
        }
        
        func beginFetchMore() {
            fetchingMore = true
            
            viewModel.load()
            
            DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
                self.fetchingMore = false
            }
        }
        
        @objc func handleRefreshControl(sender: UIRefreshControl) {
            sender.endRefreshing()
            viewModel.refresh()
        }
    }
}

标签: iosswiftuiscrollviewswiftuiswift5

解决方案


推荐阅读