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

设置UIAlertAction自定义字体后,点击时字体临时变回默认的问题

解决UIAlertAction点击时字体临时变回默认的问题

嘿,这个坑我之前踩过!你用KVC拿到内部label设置自定义attributedText的思路没问题,但为啥点击时会跳回默认字体?原因很简单:当UIAlertAction被点击时,系统会自动给label设置高亮状态的文本样式,直接覆盖了你之前设置的attributedText,虽然弹窗很快消失,但这个闪烁还是挺明显的。

给你几个靠谱的解决方案,按需选择:

方案一:用KVO监听label的attributedText变化,强制保持自定义样式

既然系统会偷偷修改label的attributedText,那我们就盯着它,改一次我们就再改回来一次:

// 假设你已经通过KVC拿到了目标label
guard let label = lb.value(forKey: "label") as? UILabel else { return }

// 给label添加KVO监听
label.addObserver(self, forKeyPath: "attributedText", options: [.new], context: nil)

// 实现监听回调方法
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
    if keyPath == "attributedText", let targetLabel = object as? UILabel {
        // 重新设置你的自定义attributedText
        targetLabel.attributedText = myMutableString
        // 记得移除监听,避免内存泄漏
        targetLabel.removeObserver(self, forKeyPath: "attributedText")
    }
}

注意:一定要在弹窗消失的时机移除KVO监听,比如在UIAlertController的completion回调里处理,不然容易引发内存泄漏问题。

方案二:用Runtime替换label的setAttributedText方法,注入自定义样式

如果觉得KVC+KVO的组合太繁琐,也可以用Runtime替换UILabel的setAttributedText:方法,让每次设置文本时都自动带上我们的自定义样式:

import ObjectiveC

// 定义关联对象的标识key
private let originalSetAttributedTextSelector = Selector(("setAttributedText:"))
private let swizzledSetAttributedTextSelector = #selector(swizzled_setAttributedText(_:))

extension UILabel {
    static func swizzleAlertLabelStyle() {
        guard let originalMethod = class_getInstanceMethod(self, originalSetAttributedTextSelector),
              let swizzledMethod = class_getInstanceMethod(self, swizzledSetAttributedTextSelector) else { return }
        
        method_exchangeImplementations(originalMethod, swizzledMethod)
    }
    
    @objc private func swizzled_setAttributedText(_ attributedText: NSAttributedString?) {
        // 先调用原方法执行系统逻辑
        self.swizzled_setAttributedText(attributedText)
        
        // 判断当前label是否属于UIAlertAction的内部控件
        if self.superview?.superview?.isKind(of: UIAlertController.self) ?? false {
            // 重新应用自定义的attributedText
            self.attributedText = myMutableString
        }
    }
}

// 在App启动时或者页面加载时执行一次方法交换
// 比如在AppDelegate的didFinishLaunchingWithOptions里
UILabel.swizzleAlertLabelStyle()

这个方法一劳永逸,所有弹窗里的Action标签都会自动应用你的样式,但要注意判断条件别影响到其他业务里的UILabel。

更安全的替代方案:用系统API设置文本样式

其实苹果提供了更安全的方式自定义UIAlertAction的文本样式,不需要访问私有属性,稳定性更高:

let customAction = UIAlertAction(title: "确定", style: .default) { _ in
    // 点击事件逻辑
}

// 设置普通状态的文本样式
customAction.setValue([
    NSAttributedString.Key.font: UIFont(name: "YourCustomFont", size: 16)!,
    NSAttributedString.Key.foregroundColor: UIColor.systemBlue
], forKey: "titleTextAttributes")

// 同时设置高亮状态的样式,避免点击时闪烁
customAction.setValue([
    NSAttributedString.Key.font: UIFont(name: "YourCustomFont", size: 16)!,
    NSAttributedString.Key.foregroundColor: UIColor.systemBlue.withAlphaComponent(0.7)
], forKey: "highlightedTitleTextAttributes")

这个方法不需要依赖私有API,能同时处理普通和高亮状态,完美解决点击时的字体闪烁问题,优先推荐使用!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 08:30:20