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

如何在一个ViewController中创建多个行为一致的Collection View?

多Collection View复用代码解决方案

核心思路

把通用的Collection View逻辑(数据源、代理、单元格配置)统一处理,通过区分不同Collection View的标识来返回对应分类的数据,避免重复写相同代码。


步骤1:整理数据结构与关联Collection View

首先在ViewController里定义存储不同分类照片的字典,同时关联所有Collection View的IBOutlet:

import UIKit

class ClothingViewController: UIViewController {
    // 关联所有分类的Collection View
    @IBOutlet weak var topsCollectionView: UICollectionView!
    @IBOutlet weak var bottomsCollectionView: UICollectionView!
    @IBOutlet weak var shoesCollectionView: UICollectionView!
    
    // 用字典存储不同分类的照片,键为分类名称,值为对应照片数组
    var clothingData: [String: [UIImage]] = [
        "tops": [],
        "bottoms": [],
        "shoes": []
    ]
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // 给所有Collection View统一设置数据源、代理
        setupCollectionViews()
    }
    
    // 统一初始化Collection View
    private func setupCollectionViews() {
        let collectionViews = [topsCollectionView, bottomsCollectionView, shoesCollectionView]
        let cellNib = UINib(nibName: "ClothingCell", bundle: nil)
        
        for cv in collectionViews {
            cv?.dataSource = self
            cv?.delegate = self
            cv?.register(cellNib, forCellWithReuseIdentifier: "ClothingCell")
        }
    }
}

步骤2:重构数据源方法,区分不同Collection View

修改UICollectionViewDataSource扩展,通过判断当前Collection View的实例(或tag)返回对应分类的数据:

extension ClothingViewController: UICollectionViewDataSource {
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        // 根据Collection View实例匹配对应分类
        switch collectionView {
        case topsCollectionView:
            return clothingData["tops"]?.count ?? 0
        case bottomsCollectionView:
            return clothingData["bottoms"]?.count ?? 0
        case shoesCollectionView:
            return clothingData["shoes"]?.count ?? 0
        default:
            return 0
        }
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "ClothingCell", for: indexPath) as! ClothingCell
        
        // 获取当前Collection View对应的照片数组
        var currentImages: [UIImage] = []
        switch collectionView {
        case topsCollectionView:
            currentImages = clothingData["tops"] ?? []
        case bottomsCollectionView:
            currentImages = clothingData["bottoms"] ?? []
        case shoesCollectionView:
            currentImages = clothingData["shoes"] ?? []
        default:
            break
        }
        
        // 统一配置单元格
        cell.clothingImageView.image = currentImages[indexPath.item]
        return cell
    }
}

如果觉得用实例判断繁琐,也可以给每个Collection View在Storyboard里设置tag(比如tops设为1,bottoms设为2),然后用tag匹配:

func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    let category: String
    switch collectionView.tag {
    case 1: category = "tops"
    case 2: category = "bottoms"
    case 3: category = "shoes"
    default: category = ""
    }
    return clothingData[category]?.count ?? 0
}

步骤3:处理上传与刷新逻辑

当用户选择分类上传照片后,把照片加到对应分类的数组,再刷新对应的Collection View:

// 上传照片时调用的方法,参数为照片和选中的分类
func addClothingImage(_ image: UIImage, toCategory category: String) {
    // 把照片添加到对应分类的数组
    clothingData[category]?.append(image)
    
    // 刷新对应的Collection View
    switch category {
    case "tops":
        topsCollectionView.reloadData()
    case "bottoms":
        bottomsCollectionView.reloadData()
    case "shoes":
        shoesCollectionView.reloadData()
    default:
        break
    }
}

常见问题排查

  • 之前所有照片只进tops分类:大概率是数据源方法里没有区分Collection View,默认返回了tops的数据,按上面的方式添加判断即可解决。
  • 修改数据源报错:检查是否所有Collection View都设置了数据源/代理,是否在Storyboard里正确关联了IBOutlet,或者单元格复用标识符是否一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 00:55:39