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

如何创建自定义UICollectionViewDelegate/DataSource并解决方法不调用问题

问题根因

  • 初始化顺序错误:你在创建collectionView时customDataSource还未完成初始化,此时给cv.dataSource赋值的是nil,后续初始化customDataSource后没有重新给collectionView的dataSource赋值,导致数据源始终为空。
  • 缺少UICollectionView必需的布局参数:你创建UICollectionView时只传入了frame,没有传入布局对象,会导致collectionView无法正常渲染内容。
  • 数据源方法不完整:你自定义的CustomDataSource没有实现必需的collectionView(_:cellForItemAt:)方法,就算数据源被调用也无法生成cell。
  • 更新数据后没有刷新:调用fill方法更新数据源后,没有主动触发collectionView的reloadData,新数据无法同步到视图。

修复方案

1. 调整MyController的初始化顺序,补充必要配置

final class MyController: UIViewController {
  private lazy var collectionView = methodCreatesCollectionView()
  private var items: [String]?
  private var customDataSource: CustomDataSource?

  init() {
    super.init(nibName: nil, bundle: nil)
    // 先初始化数据源,再创建collectionView
    customDataSource = CustomDataSource(parent: self)
    view.addSubview(collectionView)
  }

  required init?(coder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
  }

  func fill(with items: [String]) {
    self.items = items
    // 数据更新后主动刷新列表
    collectionView.reloadData()
  }

  func methodCreatesCollectionView() -> UICollectionView {
    // 补充UICollectionView必需的布局配置,这里用流布局举例
    let layout = UICollectionViewFlowLayout()
    layout.itemSize = CGSize(width: view.bounds.width, height: 60)
    layout.minimumLineSpacing = 8
    
    let cv = UICollectionView(frame: view.bounds, collectionViewLayout: layout)
    // 此时customDataSource已初始化,赋值有效
    cv.dataSource = customDataSource
    // 注册cell,后续生成cell时需要用到
    cv.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "DefaultCell")
    return cv
  }
}

2. 补全CustomDataSource的必需方法

private class CustomDataSource: NSObject, UICollectionViewDataSource {
  weak var parent: MyController?

  init(parent: MyController) {
    self.parent = parent
    super.init()
  }

  func numberOfSections(in collectionView: UICollectionView) -> Int {
    return 1
  }

  func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return parent?.items?.count ?? 0
  }

  // 补全必须实现的cell生成方法
  func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "DefaultCell", for: indexPath)
    // 你可以在这里根据items的内容给cell赋值
    cell.contentView.backgroundColor = .systemGray5
    return cell
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.10 00:21:03