Dealing with some objC API, I receive an NSDictionary<NSString *, id> *>
which translates to [String : Any]
in Swift and which I was using for NSAttributedString.addAttributes:range:.
However, this method signature has now changed with Xcode 9 and now requires an [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)
}
How to convert a [String : Any]
to a [NSAttributedStringKey : Any]
?
NSAttributedStringKey
has an initialiser that takes a String
, and you can use Dictionary
's init(uniqueKeysWithValues:)
initialiser in order to build a dictionary from a sequence of key-value tuples where each key is unique (such as is the case here).
We just have to apply a transform to attr
that converts each String
key into an NSAttributedStringKey
prior to calling Dictionary
's initialiser.
For example:
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($0.key), $0.value) }
)
attributedString.addAttributes(convertedAttributes, range: range)
}
We're using lazy
here to avoid the creation of an unnecessary intermediate array.