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

代码修改UICollectionView属性崩溃,如何在启动时访问单元格?

解决UICollectionView布局代理里访问cell导致的崩溃问题

兄弟,你这崩溃的坑我以前也踩过!核心问题太典型了——在sizeForItemAt这个方法里调用cellForItem(at:)根本拿不到已经初始化好的cell啊!

为啥会崩溃?

sizeForItemAt是UICollectionView布局代理用来提前计算单元格尺寸的方法,这时候对应的单元格还没被创建出来呢!你强行用as!解包一个nil的cell,不崩溃才怪。而且这个方法的职责就只是返回尺寸,本来就不该用来操作cell的属性。

正确调整TextView Frame的姿势

想要适配不同屏幕调整textView的frame,推荐这几个靠谱的方式:

1. 把布局逻辑放到自定义Cell内部(最推荐)

让Cell自己管理子视图的布局,这才符合MVC的职责分离。重写Cell的layoutSubviews方法,每次Cell尺寸变化时,自动调整textView的frame:

class WordsMainCollectionViewCell: UICollectionViewCell {
    let userWord = UITextView()
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        setupTextView()
    }
    
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        setupTextView()
    }
    
    private func setupTextView() {
        addSubview(userWord)
        // 先做基础配置:关闭滚动、设置字体等
        userWord.isScrollEnabled = false
        userWord.font = UIFont.systemFont(ofSize: 16)
        userWord.textContainerInset = .zero
    }
    
    override func layoutSubviews() {
        super.layoutSubviews()
        // 根据Cell的当前边界,给textView设置边距适配
        let textViewInsets = UIEdgeInsets(top: 8, left: 16, bottom: 8, right: 16)
        userWord.frame = bounds.inset(by: textViewInsets)
        
        // 如果需要根据文本内容自动调整textView高度,也可以在这里计算
        let fittingSize = userWord.sizeThatFits(CGSize(width: userWord.frame.width, height: CGFloat.greatestFiniteMagnitude))
        userWord.frame.size.height = fittingSize.height
    }
}

2. 在cellForItemAt里配置Cell时调整

当Cell真正被创建/复用的时候,在这里根据当前的Cell尺寸设置textView的frame:

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "WordsMainCell", for: indexPath) as! WordsMainCollectionViewCell
    
    // 配置文本内容
    cell.userWord.text = yourDataArray[indexPath.item]
    
    // 调整textView frame
    let textViewInsets = UIEdgeInsets(top: 8, left: 16, bottom: 8, right: 16)
    cell.userWord.frame = cell.bounds.inset(by: textViewInsets)
    
    // 测试代码可以放这里,不会崩溃
    cell.userWord.textColor = .red
    
    return cell
}

3. 动态计算Cell高度(如果需要)

如果你的Cell高度要根据textView内容自适应,不要拿Cell来计算,直接用模型数据提前算好尺寸:

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    let targetText = yourDataArray[indexPath.item]
    let textWidth = collectionView.frame.width - 32 // 减去左右16pt的边距
    let textAttributes = [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 16)]
    
    // 计算文本需要的高度
    let textSize = NSString(string: targetText).boundingRect(
        with: CGSize(width: textWidth, height: CGFloat.greatestFiniteMagnitude),
        options: .usesLineFragmentOrigin,
        attributes: textAttributes,
        context: nil
    ).size
    
    // 加上上下边距的总高度
    let cellHeight = textSize.height + 16
    return CGSize(width: collectionView.frame.width, height: cellHeight)
}

最后再划个重点

  • sizeForItemAt只负责返回尺寸,别在这儿操作Cell的任何属性!
  • Cell的子视图布局,优先让Cell自己处理,代码更易维护。
  • 动态高度计算依赖模型数据,不要依赖未创建的Cell实例。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 03:26:35