如何将[String : Any] 转换为[NSAttributedStringKey : Any]?

4
处理一些 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]

3个回答

16
NSAttributedStringKey具有一个接受字符串参数的初始化器,您可以使用Dictionaryinit(uniqueKeysWithValues:)初始化器来从一系列键值元组构建字典,其中每个键都是唯一的(正如在此处的情况)。我们只需要对attr应用一个变换,将每个String键转换为NSAttributedStringKey,然后调用Dictionary的初始化器即可。例如:
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)
}

我们在这里使用lazy来避免创建不必要的中间数组。

4
谢谢!为了全面,我还需要进行相反的操作(从[NSAttributedStringKey : Any][String : Any]),在这种情况下,代码是Dictionary(uniqueKeysWithValues: attr.lazy.map { ($0.key.rawValue, $0.value) }) - Cœur
@Hamish 为什么要使用 lazy?在这种情况下,attr.map { /* ... */ } 不是也可以吗? - Matusalem Marques
1
@MatusalemMarques 这样做可以达到相同的效果,但使用lazy可以避免创建不必要的中间数组(键值对只被迭代一次并插入到新字典中,应用给定的转换)。 - Hamish

0
你可以使用

`NSAttributedStringKey(rawValue: String)`

初始化程序。但是使用它时,即使属性字符串不受影响,它也会创建一个对象。例如,

`NSAttributedStringKey(rawValue: fakeAttribute)` 

仍然会为字典创建一个键。此外,这仅适用于iOS 11,因此在向后兼容性方面要小心使用。


0

虽然 Hamish 提供了一个完美的 Swift 答案,请注意最终我直接在 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 (https://stackoverflow.com/a/46927445/1033581)
#if __clang_major__ < 9
// Compatibility with Xcode 8-
typedef NSString * NSAttributedStringKey NS_EXTENSIBLE_STRING_ENUM;
#endif

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接