You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现显示数字的无限滚动UITableView?

解决方案

核心问题分析

你的代码主要存在两个关键问题:

  1. APICaller中使用无限while循环会导致线程卡死,永远无法执行到completion回调,因此界面无内容;同时分页请求错误返回固定的[0],而非新生成的数字。
  2. ViewController中初始数据请求放在viewDidLayoutSubviews中,会被多次触发导致重复加载;且分页时全量刷新表格,性能较差。

修改后的APICaller代码

class APICaller {
    
    private var counter = 0
    // 定义每页加载的条目数量,可按需调整
    private let pageSize = 10
    
    var isPaginating = false
    
    func fetchData(pagination: Bool = false, completion: @escaping (Result<[Int], Error>) -> Void) {
        if pagination {
            isPaginating = true
        }
        // 模拟网络请求延迟,可按需调整时长
        DispatchQueue.global().asyncAfter(deadline: .now() + (pagination ? 0.5 : 1), execute: {
            var newData = [Int]()
            
            // 生成固定数量的新数字,避免无限循环
            for _ in 0..<self.pageSize {
                self.counter += 1
                newData.append(self.counter)
            }
            
            completion(.success(newData))
            if pagination {
                self.isPaginating = false
            }
        })
    }
}

修改后的ViewController代码

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UIScrollViewDelegate {
    
    private let apiCaller = APICaller()
    
    private let tableView: UITableView  = {
        let tableView = UITableView(frame: .zero, style: .grouped)
        tableView.register(UITableViewCell.self,
                           forCellReuseIdentifier: "cell")
        return tableView
    }()
    
    private var data = [Int]()
    // 标记初始数据是否已加载,避免重复请求
    private var hasLoadedInitialData = false

    override func viewDidLoad() {
        super.viewDidLoad()
        view.addSubview(tableView)
        tableView.dataSource = self
        tableView.delegate = self
        tableView.frame = view.bounds
        
        // 加载初始数据
        loadInitialData()
    }
    
    private func loadInitialData() {
        guard !hasLoadedInitialData else { return }
        hasLoadedInitialData = true
        apiCaller.fetchData(pagination: false) { [weak self] result in
            switch result {
            case .success(let initialData):
                self?.data.append(contentsOf: initialData)
                DispatchQueue.main.async {
                    self?.tableView.reloadData()
                }
            case .failure(_):
                break
            }
        }
    }
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return data.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
        cell.textLabel?.text = String(data[indexPath.row])
        return cell
    }

    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        let position = scrollView.contentOffset.y
        // 滚动到距离底部100px时触发分页加载
        if position > (tableView.contentSize.height - 100 - scrollView.frame.size.height) {
            guard !apiCaller.isPaginating else { return }
            apiCaller.fetchData(pagination: true) { [weak self] result in
                switch result {
                case .success(let moreData):
                    let startIndex = self?.data.count ?? 0
                    self?.data.append(contentsOf: moreData)
                    // 仅插入新行,而非全量刷新,提升性能
                    DispatchQueue.main.async {
                        let indexPaths = (startIndex..<(startIndex + moreData.count)).map {
                            IndexPath(row: $0, section: 0)
                        }
                        self?.tableView.insertRows(at: indexPaths, with: .automatic)
                    }
                case .failure(_):
                    break
                }
            }
        }
    }
}

关键修改说明

  1. APICaller:
    • 移除无限while循环,改用for循环生成固定数量的新数字,避免线程卡死。
    • 统一初始加载和分页加载的返回逻辑,直接返回本次生成的连续数字。
  2. ViewController:
    • 将初始数据请求移至viewDidLoad,并添加标记避免重复加载。
    • 分页时使用insertRows而非全量reloadData,提升滚动流畅度。

内容的提问来源于stack exchange,提问作者Mikl.hart

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 23:09:33