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,提问作者이진성
相关产品推荐
相关产品推荐

