Swift新手求助:如何为NSAttributedStringKey创建适配枚举类型?
嘿,我完全懂你的纠结——用Any虽然能暂时解决问题,但Swift的类型安全优势就没了,后续很容易因为传错值踩坑。其实你想要的用枚举约束富文本属性值的思路非常靠谱,只是需要利用枚举的关联值特性来适配不同类型的属性需求,毕竟NSAttributedString的属性值本身就是多样的(比如颜色是UIColor,描边宽度是NSNumber)。
下面给你一套完整的实现方案:
1. 定义带关联值的枚举
先创建一个枚举,把你需要支持的属性值类型都用关联值包起来,这样就能严格约束允许传入的类型:
import UIKit enum AttributeValue { // 对应颜色类属性,比如foregroundColor、backgroundColor case color(UIColor) // 对应数值类属性,比如strokeWidth、baselineOffset case number(NSNumber) // 对应字体属性,比如font case font(UIFont) // 可以根据你项目的需求,继续添加其他类型,比如字符串(用于link属性等) // case string(String) }
2. 给枚举添加转换逻辑
因为NSAttributedString最终需要的是Any类型的属性值,我们给枚举加一个计算属性,把关联值提取出来:
extension AttributeValue { var rawValue: Any { switch self { case .color(let color): return color case .number(let number): return number case .font(let font): return font // 如果添加了其他case,在这里对应处理 // case .string(let str): return str } } }
3. 实际使用方式
现在你可以用这个枚举来定义属性字典,完全不用Any:
// 定义符合类型约束的属性字典 let myAttributes: [NSAttributedStringKey: AttributeValue] = [ .foregroundColor: .color(UIColor.systemRed), .strokeWidth: .number(NSNumber(value: 2.0)), .font: .font(UIFont.systemFont(ofSize: 16, weight: .bold)) ] // 转换成NSAttributedString能识别的字典格式 let usableAttributes = myAttributes.mapValues { $0.rawValue } // 创建富文本字符串 let attributedText = NSAttributedString(string: "Hello Swift", attributes: usableAttributes)
进阶优化:简化调用
如果觉得每次转换麻烦,可以给NSAttributedString写个扩展,直接接受我们的枚举字典:
extension NSAttributedString { convenience init(string: String, attributeValues: [NSAttributedStringKey: AttributeValue]) { let convertedAttributes = attributeValues.mapValues { $0.rawValue } self.init(string: string, attributes: convertedAttributes) } } // 调用起来更简洁 let attributes: [NSAttributedStringKey: AttributeValue] = [ .foregroundColor: .color(UIColor.systemBlue), .strokeWidth: .number(3) ] let easyAttributedText = NSAttributedString(string: "简化调用", attributeValues: attributes)
这样一来,你既享受了Swift的类型安全(只能传入枚举定义好的合法类型),又完全符合NSAttributedString的要求,再也不用依赖Any啦!
内容的提问来源于stack exchange,提问作者INFORMATIKER IM ALL
相关产品推荐
相关产品推荐

