如何将 [String : Any] 转换为 [NSAttributedStringKey : Any]
How to convert [String : Any] to [NSAttributedStringKey : Any]
处理一些 objC API,我收到一个 NSDictionary<NSString *, id> *>
,它在 Swift 中转换为 [String : Any]
,我将其用于 NSAttributedString.addAttributes:range:。
但是,此方法签名现已更改为 Xcode 9,现在需要 [NSAttributedStringKey : Any]
。
let attr: [String : Any]? = OldPodModule.getMyAttributes()
// Cannot assign value of type '[String : Any]?' to type '[NSAttributedStringKey : Any]?'
let newAttr: [NSAttributedStringKey : Any]? = attr
if let newAttr = newAttr {
myAttributedString.addAttributes(newAttr, range: range)
}
如何将 [String : Any]
转换为 [NSAttributedStringKey : Any]
?
NSAttributedStringKey
有 an initialiser that takes a String
, and you can use Dictionary
's init(uniqueKeysWithValues:)
初始化器,以便从一系列键值元组构建字典,其中每个键都是唯一的(例如这里的情况)。
我们只需对 attr
应用转换,在调用 Dictionary
的初始化程序之前将每个 String
键转换为 NSAttributedStringKey
。
例如:
let attributes: [String : Any]? = // ...
let attributedString = NSMutableAttributedString(string: "hello world")
let range = NSRange(location: 0, length: attributedString.string.utf16.count)
if let attributes = attributes {
let convertedAttributes = Dictionary(uniqueKeysWithValues:
attributes.lazy.map { (NSAttributedStringKey([=10=].key), [=10=].value) }
)
attributedString.addAttributes(convertedAttributes, range: range)
}
我们在这里使用 lazy
以避免创建不必要的中间数组。
您可以使用
`NSAttributedStringKey(rawValue: String)`
初始化程序。但是,即使属性字符串不受影响,它也会创建一个对象。例如,
`NSAttributedStringKey(rawValue: fakeAttribute)`
仍会为字典创建键。此外,这仅在 iOS 11 中可用,因此请谨慎使用以实现向后兼容性。
虽然 Hamish 提供了完美的 Swift 答案,但请注意最后 I solved 问题直接在 Objective-C API 级别。如果您无法控制源代码,也可以使用小型 Objective-C 包装器来完成。
我们只需将 NSDictionary<NSString *, id> *
替换为 NSDictionary<NSAttributedStringKey, id> *
并添加 typedef
以与早期版本的 Xcode 兼容:
#ifndef NS_EXTENSIBLE_STRING_ENUM
// Compatibility with Xcode 7
#define NS_EXTENSIBLE_STRING_ENUM
#endif
// Testing Xcode version (
#if __clang_major__ < 9
// Compatibility with Xcode 8-
typedef NSString * NSAttributedStringKey NS_EXTENSIBLE_STRING_ENUM;
#endif
处理一些 objC API,我收到一个 NSDictionary<NSString *, id> *>
,它在 Swift 中转换为 [String : Any]
,我将其用于 NSAttributedString.addAttributes:range:。
但是,此方法签名现已更改为 Xcode 9,现在需要 [NSAttributedStringKey : Any]
。
let attr: [String : Any]? = OldPodModule.getMyAttributes()
// Cannot assign value of type '[String : Any]?' to type '[NSAttributedStringKey : Any]?'
let newAttr: [NSAttributedStringKey : Any]? = attr
if let newAttr = newAttr {
myAttributedString.addAttributes(newAttr, range: range)
}
如何将 [String : Any]
转换为 [NSAttributedStringKey : Any]
?
NSAttributedStringKey
有 an initialiser that takes a String
, and you can use Dictionary
's init(uniqueKeysWithValues:)
初始化器,以便从一系列键值元组构建字典,其中每个键都是唯一的(例如这里的情况)。
我们只需对 attr
应用转换,在调用 Dictionary
的初始化程序之前将每个 String
键转换为 NSAttributedStringKey
。
例如:
let attributes: [String : Any]? = // ...
let attributedString = NSMutableAttributedString(string: "hello world")
let range = NSRange(location: 0, length: attributedString.string.utf16.count)
if let attributes = attributes {
let convertedAttributes = Dictionary(uniqueKeysWithValues:
attributes.lazy.map { (NSAttributedStringKey([=10=].key), [=10=].value) }
)
attributedString.addAttributes(convertedAttributes, range: range)
}
我们在这里使用 lazy
以避免创建不必要的中间数组。
您可以使用
`NSAttributedStringKey(rawValue: String)`
初始化程序。但是,即使属性字符串不受影响,它也会创建一个对象。例如,
`NSAttributedStringKey(rawValue: fakeAttribute)`
仍会为字典创建键。此外,这仅在 iOS 11 中可用,因此请谨慎使用以实现向后兼容性。
虽然 Hamish 提供了完美的 Swift 答案,但请注意最后 I solved 问题直接在 Objective-C API 级别。如果您无法控制源代码,也可以使用小型 Objective-C 包装器来完成。
我们只需将 NSDictionary<NSString *, id> *
替换为 NSDictionary<NSAttributedStringKey, id> *
并添加 typedef
以与早期版本的 Xcode 兼容:
#ifndef NS_EXTENSIBLE_STRING_ENUM
// Compatibility with Xcode 7
#define NS_EXTENSIBLE_STRING_ENUM
#endif
// Testing Xcode version (
#if __clang_major__ < 9
// Compatibility with Xcode 8-
typedef NSString * NSAttributedStringKey NS_EXTENSIBLE_STRING_ENUM;
#endif