设置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
相关产品推荐
相关产品推荐

