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

能否使用XIB在UICollectionViewListCell中创建自定义视图?

用XIB实现UICollectionViewListCell自定义视图+编辑功能

完全可以用XIB实现这个需求,不用依赖SwiftUI。下面是具体的实现步骤和代码示例:

1. 创建自定义内容视图的XIB

  • 新建一个UIView子类(命名为CustomContentView),同时创建对应的XIB文件
  • 在XIB中添加你需要的控件(比如UIButton、UITextView),设置好约束确保控件布局正确
  • 在CustomContentView类中关联XIB里的控件,提供配置方法方便后续更新内容:
import UIKit

class CustomContentView: UIView {
    @IBOutlet weak var titleButton: UIButton!
    @IBOutlet weak var contentTextView: UITextView!
    
    func configure(with title: String, content: String) {
        titleButton.setTitle(title, for: .normal)
        contentTextView.text = content
    }
    
    // 从XIB加载的类方法
    static func loadFromNib() -> CustomContentView {
        let nib = UINib(nibName: "CustomContentView", bundle: nil)
        return nib.instantiate(withOwner: nil, options: nil).first as! CustomContentView
    }
}

2. 自定义UICollectionViewListCell子类

创建UICollectionViewListCell的子类(命名为CustomListCell),在其中加载并添加自定义内容视图:

import UIKit

class CustomListCell: UICollectionViewListCell {
    private var customContentView: CustomContentView!
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        setupContentView()
    }
    
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        setupContentView()
    }
    
    private func setupContentView() {
        customContentView = CustomContentView.loadFromNib()
        customContentView.translatesAutoresizingMaskIntoConstraints = false
        contentView.addSubview(customContentView)
        
        // 设置约束让自定义视图铺满contentView
        NSLayoutConstraint.activate([
            customContentView.topAnchor.constraint(equalTo: contentView.topAnchor),
            customContentView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor),
            customContentView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor),
            customContentView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor)
        ])
        
        // 配置cell的更新逻辑
        configurationUpdateHandler = { [weak self] cell, state in
            guard let self = self else { return }
            // 根据状态更新accessories
            var accessories: [UICellAccessory] = []
            if state.isEditing {
                accessories.append(.reorder())
                accessories.append(.delete())
            }
            cell.accessories = accessories
            
            // 从configuration中获取数据更新自定义视图
            if let config = cell.configuration as? CustomCellConfiguration {
                self.customContentView.configure(with: config.title, content: config.content)
            }
        }
    }
}

// 自定义Configuration,用于传递cell数据
struct CustomCellConfiguration: UIContentConfiguration, Hashable {
    var title: String
    var content: String
    
    func makeContentView() -> UIView & UIContentView {
        fatalError("不需要实现,因为我们用自定义视图")
    }
    
    func updated(for state: UIConfigurationState) -> CustomCellConfiguration {
        return self
    }
}

3. 配置UICollectionView

在ViewController中设置collectionView的布局、注册cell,并实现编辑和滑动删除逻辑:

import UIKit

class ViewController: UIViewController {
    private var collectionView: UICollectionView!
    private var data = ["Item 1", "Item 2", "Item 3"].map { (title: $0, content: "Content for \($0)") }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        setupCollectionView()
        // 添加编辑按钮
        navigationItem.rightBarButtonItem = editButtonItem
    }
    
    private func setupCollectionView() {
        // 使用列表布局
        let layout = UICollectionViewCompositionalLayout.list(using: UICollectionLayoutListConfiguration(appearance: .insetGrouped))
        collectionView = UICollectionView(frame: view.bounds, collectionViewLayout: layout)
        collectionView.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(collectionView)
        
        NSLayoutConstraint.activate([
            collectionView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
            collectionView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            collectionView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
            collectionView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor)
        ])
        
        // 注册自定义cell
        collectionView.register(CustomListCell.self, forCellWithReuseIdentifier: "CustomListCell")
        collectionView.dataSource = self
        collectionView.delegate = self
        
        // 允许编辑时的操作
        collectionView.allowsSelectionDuringEditing = true
        collectionView.allowsMultipleSelectionDuringEditing = true
    }
    
    override func setEditing(_ editing: Bool, animated: Bool) {
        super.setEditing(editing, animated: animated)
        collectionView.setEditing(editing, animated: animated)
    }
}

// MARK: - UICollectionViewDataSource
extension ViewController: UICollectionViewDataSource {
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return data.count
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CustomListCell", for: indexPath) as! CustomListCell
        let item = data[indexPath.item]
        cell.configuration = CustomCellConfiguration(title: item.title, content: item.content)
        return cell
    }
    
    // 处理删除
    func collectionView(_ collectionView: UICollectionView, commit editingStyle: UICollectionViewCell.EditingStyle, forItemAt indexPath: IndexPath) {
        if editingStyle == .delete {
            data.remove(at: indexPath.item)
            collectionView.deleteItems(at: [indexPath])
        }
    }
    
    // 允许重排
    func collectionView(_ collectionView: UICollectionView, canMoveItemAt indexPath: IndexPath) -> Bool {
        return true
    }
    
    // 处理重排
    func collectionView(_ collectionView: UICollectionView, moveItemAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
        let movedItem = data.remove(at: sourceIndexPath.item)
        data.insert(movedItem, at: destinationIndexPath.item)
    }
}

// MARK: - UICollectionViewDelegate
extension ViewController: UICollectionViewDelegate {
    // 实现滑动删除
    func collectionView(_ collectionView: UICollectionView, trailingSwipeActionsConfigurationForItemAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
        let deleteAction = UIContextualAction(style: .destructive, title: "删除") { [weak self] _, _, completion in
            guard let self = self else { return }
            self.data.remove(at: indexPath.item)
            collectionView.deleteItems(at: [indexPath])
            completion(true)
        }
        return UISwipeActionsConfiguration(actions: [deleteAction])
    }
}

关键说明

  • 自定义内容视图通过XIB创建,完全复用你之前的XIB开发习惯
  • UICollectionViewListCell的accessories属性在编辑模式下自动添加重排和删除控件,无需额外自定义
  • 通过自定义UIContentConfiguration传递数据,配合configurationUpdateHandler统一更新cell状态和内容
  • 用标准的UICollectionView代理方法实现删除、重排和滑动删除逻辑,和传统UICollectionCell的编辑逻辑完全兼容

内容的提问来源于stack exchange,提问作者Cheok Yan Cheng

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 03:25:02