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

UICollectionView自定义附件动画卡顿:无需披露指示器的解决方法

解决UICollectionView组合布局中开关点击卡顿问题

以下是一个采用组合布局(列表布局)和Diffable Data Source的UICollectionView示例应用:

import UIKit

class ViewController: UIViewController {
    var bool = false {
        didSet {
            var snapshot = dataSource.snapshot()
            snapshot.reconfigureItems(snapshot.itemIdentifiers)
            dataSource.apply(snapshot, animatingDifferences: true)
        }
    }
    
    var collectionView: UICollectionView!
    
    var dataSource: UICollectionViewDiffableDataSource<String, String>!
    
    var snapshot: NSDiffableDataSourceSnapshot<String, String> {
        var snapshot = NSDiffableDataSourceSnapshot<String, String>()
        snapshot.appendSections(["section"])
        snapshot.appendItems(["id"])
        return snapshot
    }

    override func viewDidLoad() {
        super.viewDidLoad()
                        
        configureHierarchy()
        configureDataSource()
    }
    
    func configureHierarchy() {
        collectionView = .init(frame: view.bounds, collectionViewLayout: createLayout())
        view.addSubview(collectionView)
        collectionView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
    }
    
    func createLayout() -> UICollectionViewLayout {
        let configuration = UICollectionLayoutListConfiguration(appearance: .insetGrouped)
        return UICollectionViewCompositionalLayout.list(using: configuration)
    }
    
    func configureDataSource() {
        let cellRegistration = UICollectionView.CellRegistration<UICollectionViewListCell, String> { [weak self] cell, indexPath, itemIdentifier in
            guard let self else { return }
            
            let _switch = UISwitch()
            cell.accessories = [
                .customView(configuration: .init(
                    customView: _switch,
                    placement: .trailing())
                ),
//                .disclosureIndicator()
            ]
            _switch.isOn = bool
            _switch.addTarget(self, action: #selector(toggleBool), for: .valueChanged)
        }
        
        dataSource = .init(collectionView: collectionView) { collectionView, indexPath, itemIdentifier in
            collectionView.dequeueConfiguredReusableCell(using: cellRegistration, for: indexPath, item: itemIdentifier)
        }
        
        dataSource.apply(self.snapshot, animatingDifferences: false)
    }
    
    @objc func toggleBool() {
        bool.toggle()
    }
}

问题现象与环境

  • 现象:点击开关时界面出现卡顿;取消注释代码中的.disclosureIndicator()后,卡顿消失。
  • 环境:Xcode 15.3、iOS 17.4的iPhone 15 Pro模拟器、macOS Sonoma 14.4.1、M1芯片8GB内存的MacBook Air

需求

如何在不添加披露指示器的前提下解决开关动画卡顿问题?

注:不希望在视图控制器类级别声明开关(实际项目中控件数量较多);在configureDataSource()级别声明开关虽能解决,但多元素列表时仍不便。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 16:43:22