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

iOS(Swift)中点击A视图控制器按钮跳转后B视图控制器内CollectionView不显示问题排查求助

CollectionView 不显示问题排查与修复方案

我帮你排查了代码里的几个关键问题,这些都是导致CollectionView完全不显示的核心原因👇

问题1:使用了抽象的UICollectionViewLayout

你创建CollectionView时用了let layout = UICollectionViewLayout(),这是一个抽象基类,不能直接实例化使用——CollectionView需要具体的布局规则(比如流式布局)才能知道如何排列单元格,没有有效布局的话,单元格根本不会被渲染。

修复方案:替换成UICollectionViewFlowLayout,还可以根据需求设置item大小、间距等参数。

问题2:加载JSON数据后未刷新CollectionView

你的getJson方法成功获取数据并更新了nameArray,但没有通知CollectionView重新加载数据,所以即使数据准备好了,UI也不会同步更新。

修复方案:在数据处理完成后调用collectionView?.reloadData(),注意要在主线程执行UI操作。

问题3:CollectionViewCell未将UIImageView添加到contentView

你的ChamCellCollectionViewCell里创建了imageView,但没有把它添加到cell的contentView上,导致图片无法显示在界面上。

修复方案:在init(frame:)方法里将imageView添加到contentView。

问题4:强制解包存在崩溃风险(可选优化)

代码里的cellUrl!、cellData!、as!这些强制解包操作,一旦JSON格式错误或者资源不存在,会直接导致APP崩溃,建议用可选绑定做容错处理。


修复后的完整代码

A视图控制器代码(无需修改)

//MARK: 4. @objc Button Action
@objc func topHand(){
    let cham = ChampViewViewController()
    cham.modalPresentationStyle = .fullScreen
    present(cham, animated: true, completion: nil)
}

B视图控制器代码

class ChampViewViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource{
    var nameArray = [String]()
    private var collectionView : UICollectionView?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .white // 可选:设置背景色,方便调试查看CollectionView范围
        
        let indenti = "top"
        // 替换为具体的流式布局,并设置布局参数
        let layout = UICollectionViewFlowLayout()
        layout.itemSize = CGSize(width: 100, height: 100) // 自定义item大小
        layout.minimumInteritemSpacing = 10
        layout.minimumLineSpacing = 10
        layout.sectionInset = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10)
        
        getJson(line: indenti)
        
        collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
        collectionView?.delegate = self
        collectionView?.dataSource = self
        collectionView?.register(ChamCellCollectionViewCell.self, forCellWithReuseIdentifier: ChamCellCollectionViewCell.identifier)
        collectionView?.backgroundColor = .lightGray // 可选:设置CollectionView背景色,方便调试
        
        guard let collectionsView = collectionView else { return }
        view.addSubview(collectionsView)
        // 用AutoLayout替代frame,适配不同屏幕尺寸
        collectionsView.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            collectionsView.topAnchor.constraint(equalTo: view.topAnchor),
            collectionsView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            collectionsView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
            collectionsView.bottomAnchor.constraint(equalTo: view.bottomAnchor)
        ])
    }
    
    private func getJson(line:String){
        guard let cellUrl = Bundle.main.url(forResource: line, withExtension: "json"),
              let cellData = NSData(contentsOf: cellUrl) as Data? else {
            print("JSON文件加载失败,请检查文件名是否正确")
            return
        }
        do {
            guard let modelJson = try JSONSerialization.jsonObject(with: cellData, options: .allowFragments ) as? [[String : Any]] else {
                print("JSON格式错误,请检查结构是否符合预期")
                return
            }
            var models : [Model] = []
            modelJson.forEach { dic in
                // 用可选绑定处理每个字段,避免强制解包崩溃
                guard let name = dic["이름"] as? String,
                      let line = dic["주라인"] as? String,
                      let type = dic["성향"] as? String,
                      let hp = dic["체력"] as? Int,
                      let hpRe = dic["추가체력"] as? Int,
                      let attackPower = dic["공격력"] as? Double,
                      let attackPowerRe = dic["추가공격력"] as? Double,
                      let attackSpeed = dic["공속"] as? Double,
                      let attackSpeedRe = dic["추가공속"] as? Double,
                      let defensive = dic["방어력"] as? Double,
                      let defensiveRe = dic["추가방어력"] as? Double,
                      let magicDefensive = dic["마저"] as? Double,
                      let magicDefensiveRe = dic["추가마저"] as? Double,
                      let row = dic["row"] as? Int,
                      let column = dic["column"] as? Int else {
                    print("JSON字段缺失或类型错误,跳过当前数据")
                    return
                }
                let newModel = Model(name: name, line: line, type: type, hp: hp, hpRe: hpRe, attackPower: attackPower, attackPowerRe: attackPowerRe, attackSpeed: attackSpeed, attackSpeedRe: attackSpeedRe, defensive: defensive, defensiveRe: defensiveRe, magicDefensive: magicDefensive, magicDefensiveRe: magicDefensiveRe, row: row, column: column)
                models.append(newModel)
            }
            nameArray = models.map { $0.name }
            // 数据更新后,在主线程刷新CollectionView
            DispatchQueue.main.async {
                self.collectionView?.reloadData()
            }
        }catch {
            print("JSON解析失败:\(error.localizedDescription)")
        }
    }
    
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return nameArray.count // 直接用数组长度,不需要额外维护count变量
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: ChamCellCollectionViewCell.identifier, for: indexPath) as? ChamCellCollectionViewCell else {
            print("Cell注册失败或类型不匹配")
            return UICollectionViewCell()
        }
        // 用nameArray里的名字动态获取图片,替代固定的"가렌"
        let imageName = nameArray[indexPath.item]
        cell.imageConfigure(with: UIImage(named: imageName))
        return cell
    }
}

CollectionViewCell代码

import UIKit
class ChamCellCollectionViewCell : UICollectionViewCell{
    static let identifier = "ChamCellCollectionViewCell"
    private let imageView : UIImageView = {
        let image = UIImageView()
        image.contentMode = .scaleAspectFit
        image.clipsToBounds = true // 可选:防止图片超出cell范围
        return image
    }()
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        contentView.addSubview(imageView) // 将imageView添加到contentView,这是显示的关键
        contentView.backgroundColor = .white // 可选:设置cell背景色
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    func imageConfigure(with image : UIImage?) {
        imageView.image = image
    }
    
    override func layoutSubviews() {
        super.layoutSubviews()
        imageView.frame = contentView.bounds
    }
    
    override func prepareForReuse() {
        super.prepareForReuse()
        imageView.image = nil
    }
}

内容的提问来源于stack exchange,提问作者이진성

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 03:02:29