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

iOS17-18中UILabel设置NSAttributedString时NSFont为nil崩溃求助

解决方案:iOS17+设置NSAttributedString到UILabel时的NSFont nil崩溃问题

问题分析

从Crash日志和代码来看,崩溃仅出现在iOS17及以上版本(17.6.1、18),是系统处理UILabel的attributedText时,尝试给字典设置nil的NSFont值导致的。虽然代码里显式创建了字体对象,但存在两种潜在触发场景:

  • 极端情况下UIFont.systemFont(ofSize:weight:)可能返回nil(比如系统字体库异常、动态字体缩放的极端值)
  • iOS17+的UIKit内部在合成富文本属性时,可能出现属性丢失或nil注入的bug(尤其在cell复用场景下)

具体修复方案

1. 确保字体创建非空,添加兜底逻辑

修改prepareRating()里的字体创建代码,强制保证字体不为nil,兜底到系统默认字体:

private func prepareRating() {
    // Rating Status
    if let commentCount = hotel.commentCount, let ratingtext = hotel.averageScoreText {
        let commentText = (commentCount >= 3 ? " (\(commentCount) \(TextKey.hotelComment.localized))" : "")
        // 字体创建添加兜底,避免返回nil
        let boldFont = UIFont.systemFont(ofSize: 15, weight: .bold) ?? UIFont.systemFont(ofSize: 15)
        let regularFont = UIFont.systemFont(ofSize: 12) ?? UIFont.systemFont(ofSize: 12)
        let titleColor = UIColor.blue
        let mutableAttributedString = NSMutableAttributedString()
        mutableAttributedString.append(NSAttributedString(string: ratingtext, attributes: [.font: boldFont, .foregroundColor: titleColor]))
        mutableAttributedString.append(NSAttributedString(string: commentText, attributes: [.font: regularFont, .foregroundColor: titleColor]))
        self.ratingStatusAttributed = mutableAttributedString
    } else {
        // 兜底:条件不满足时设置空富文本,避免传递nil
        self.ratingStatusAttributed = NSAttributedString(string: "")
    }
}

2. 给UILabel设置默认字体,避免系统合成时无 fallback

在HotelListTableViewCell的configure方法里提前给label设置默认字体,或者在xib/storyboard中配置明确的默认字体:

func configure(with data: HotelListPresentation) {
    let rating = data.averageScore ?? 0
    ratingLabel.text = rating.ratingDescription
    ratingBackgroundView.tintColor = data.averageScoreColor
    ratingStackView.isHidden = rating == 0 ? true : false
    
    // 提前设置label默认字体,防止系统合成富文本时找不到字体
    if ratingStatusLabel.font == nil {
        ratingStatusLabel.font = UIFont.systemFont(ofSize: 12)
    }
    // 处理nil情况,避免给attributedText设置nil
    ratingStatusLabel.attributedText = data.ratingStatusAttributed ?? NSAttributedString(string: "")
}

3. 预检查NSAttributedString的所有属性(可选,彻底排查用)

如果崩溃仍间歇性出现,可以添加工具方法遍历富文本属性,确保NSFont不为nil:

extension NSAttributedString {
    func sanitizedForLabel() -> NSAttributedString {
        let mutable = NSMutableAttributedString(attributedString: self)
        mutable.enumerateAttributes(in: NSRange(location: 0, length: mutable.length), options: []) { attrs, range, stop in
            var safeAttrs = attrs
            if safeAttrs[.font] == nil {
                // 替换为默认字体
                safeAttrs[.font] = UIFont.systemFont(ofSize: 12)
                mutable.setAttributes(safeAttrs, range: range)
            }
        }
        return mutable
    }
}

设置时使用:

ratingStatusLabel.attributedText = data.ratingStatusAttributed?.sanitizedForLabel() ?? NSAttributedString(string: "")

4. 优化cell复用逻辑(可选)

如果是cell复用导致的极端场景,在prepareForReuse()中重置状态:

override func prepareForReuse() {
    super.prepareForReuse()
    ratingStatusLabel.attributedText = nil
    ratingStatusLabel.font = UIFont.systemFont(ofSize: 12) // 重置默认字体
}

总结

核心思路是确保字体属性绝对非空,同时给UILabel提供明确的默认字体兜底,避免iOS17+系统在合成富文本时出现nil字典操作。以上方案可覆盖绝大多数间歇性触发的场景。

内容的提问来源于stack exchange,提问作者Yılmaz edis

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 14:20:20