如果我有一个类型为Dictionary<String, MyEnum>
的字典,我无法弄清楚如何将其转换为NSDictionary,因此我可以通过NSJSONSerialize.dataWithJSONObject
将其序列化为JSON。
编译器告诉我“Dictionary<String, MyEnum> is not convertible to NSDictionary
”。我是否需要使用enum a la
var newDict = Dictionary<String, String> (or <String, AnyObject>);
for (key, val) in oldDict {
newDict[key] = val;
}
还是有更好的方法吗?
答案 0 :(得分:5)
NSJSONSerialize
和朋友只能处理对应于JSON本机数据类型的NSObject子节点(NSNumber,NSString,NSArray,NSDictionary和NSNull)的小子集。此外,如果键和值都是NSObject或者本身可以转换为NSObject(字符串和数字类型),则只能将Dictionary转换为NSDictionary。
为了序列化您的词典,您需要将Enum转换为其中一个NSJSONSerialize数据类型,类似于您的示例:
enum MyEnum : String {
case one = "one"
case two = "two"
}
let dict = ["one":MyEnum.one, "two":MyEnum.two]
var newDict = Dictionary<String, String>()
for (key, val) in dict {
newDict[key] = val.rawValue
}
let data = NSJSONSerialization.dataWithJSONObject(newDict, options: .allZeros, error: nil)
作为替代方案,由于这种操作相当普遍,您可能需要考虑将此类别添加到Dictionary中,这为其提供了方便的map
函数:
extension Dictionary {
init(_ pairs: [Element]) {
self.init()
for (k, v) in pairs {
self[k] = v
}
}
func map<K: Hashable, V>(transform: Element -> (K, V)) -> [K: V] {
return Dictionary<K, V>(Swift.map(self, transform))
}
}
完成后,转换只是:
let mapped = dict.map { (key, value) in (key, value.rawValue) }
答案 1 :(得分:0)
public protocol EnumCollection: Hashable {
static func cases() -> AnySequence<Self>
static var allValues: [Self] { get }
}
public extension EnumCollection {
public static func cases() -> AnySequence<Self> {
return AnySequence { () -> AnyIterator<Self> in
var raw = 0
return AnyIterator {
let current: Self = withUnsafePointer(to: &raw) { $0.withMemoryRebound(to: self, capacity: 1) { $0.pointee } }
guard current.hashValue == raw else {
return nil
}
raw += 1
return current
}
}
}
public static var allValues: [Self] {
return Array(self.cases())
}
}
public enum ScreenName: String, EnumCollection
{
case HomeView = "Home View"
case SignUpViewController = "Domain Validate View"
var name: String {
get { return String(describing: self) }
}
var description: String {
get { return String (self.rawValue) }
}
// a dictionary mapping the raw values to the values
static var allValuesDictionary: [String : String]{
var values = [String : String]()
let mirror = Mirror(reflecting: ScreenName.allValues)
for (_, v) in mirror.children{
guard let screenName = v as? ScreenName else{continue}
values[screenName.name] = screenName.description
}
return values
}
}
现在您可以调用方法allValuesDictionary
将返回带有<key, value> = <case, rawValue>
<HomeView, "Home View">, <SignUpViewController, "Domain Validate View">