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

时间:2017-06-07 08:48:42

标签: swift nsattributedstring swift4

处理了一些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 个答案:

答案 0 :(得分:14)

NSAttributedStringKeyan initialiser that takes a String,您可以使用Dictionary的{​​{3}}初始化程序,以便从一系列键值元组中构建字典,其中每个键都是独特的(例如这里的情况)。

我们只需将变换应用于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来避免创建不必要的中间数组。

答案 1 :(得分:0)

您可以使用

`NSAttributedStringKey(rawValue: String)`

初​​始化。但是,有了这个,它将创建一个对象,即使属性字符串不会受到影响。例如,

`NSAttributedStringKey(rawValue: fakeAttribute)` 

仍然会为字典创建一个键。此外,这仅适用于iOS 11,因此请谨慎使用以实现向后兼容。

答案 2 :(得分:0)

虽然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 (https://stackoverflow.com/a/46927445/1033581)
#if __clang_major__ < 9
// Compatibility with Xcode 8-
typedef NSString * NSAttributedStringKey NS_EXTENSIBLE_STRING_ENUM;
#endif