如何使用NSKeyedArchiver实现在Swift中保存不同字典的通用方法?

时间:2014-11-11 11:55:57

标签: generics dictionary swift nskeyedarchiver

很抱歉,如果这是一个简单的问题,但我找不到三天的答案。我是Swift的新手。

问题:我想使用Swift-Enum-Type作为不同Swift-Dictionaries的KEY,并以通用方式使用NSKeydArchiver保存这些词典。

首先,我为枚举和词典显示了一些简单的示例代码(我知道,我可以将字典值直接集成到enum声明中作为rawValues,但这不是我的问题,我的问题是保存字典NSKeydArchiver - >见下面的函数)

// ------------------------------------------------------
// Enumerations and Dictionaries
// ------------------------------------------------------
enum helloOptions {
    case option1
    case option2
    case option3
}

enum someOtherEnum {
    case green
    case red
    case blue
}

var myDictionary01 : Dictionary<helloOptions, String> = [helloOptions.option1 : "Hello", helloOptions.option2 : "Welcome", helloOptions.option3 : "Nice to see you"]

var myDictionary02 : Dictionary<someOtherEnum, Int> = [someOtherEnum.green : 22, someOtherEnum.red : 11, someOtherEnum.blue : 999]

这是我对saveFunction的工作实现,但遗憾的是它不是一种通用方式,因为我需要为应用程序中的所有枚举多次实现此功能。

func saveDictionary(myDictionary: Dictionary<helloOptions, AnyObject>, myFileName: String, myDataFolder: DataFolder) -> Bool {

    let completeDataPath = makeCompletePathToFile(myFileName, myDataFolder)

    let saveSuccess : Bool = NSKeyedArchiver.archiveRootObject(myDictionary, toFile: completeDataPath)
    if !saveSuccess {
        println("Some problem saving Dictionary")
    }
    return saveSuccess
}

所以我想要一些通用的枚举类型,比如&#34; AnyEnumType&#34;为了以通用方式使用该功能:

func saveDictionary(myDictionary: Dictionary<AnyEnumType, AnyObject>, myFileName: String, myDataFolder: DataFolder) -> Bool {
 ... 
}

但是这当然会导致编译错误&#34;使用未声明的类型&#34; AnyEnumType&#34;&#34;

我尝试使用typeAlias,使用TypePlaceholders <T : Hashable>等等,但我无法实现它。

如何实现这样的功能

func saveDictionary(myDictionary: Dictionary<AnyKeyType, AnyObject>, myFileName: String, myDataFolder: DataFolder) -> Bool { ..
}

通过声明此通用类型&#34; AnyKeyType&#34;遵循协议Hashable,Equitable,... 这使我能够使用String或Enum.Member for Key ???

1 个答案:

答案 0 :(得分:0)

这样的事可能有用:

protocol EnumType {
    typealias RawType
    init?(rawValue: RawType)
    var rawValue: RawType { get }
}

enum Hello: String, EnumType {
    case Option1 = "Option1"
    case Option2 = "Option2"
}

func toArchivableDictionaryWithEnumerationKeys<E: EnumType, T>(dictionary: Dictionary<E, T>) -> Dictionary<E.RawType, T> {
    var result = Dictionary<E.RawType, T>()
    // Tried to use reduce here, but couldn't make it work
    for (key, value) in dictionary {
        result[key.rawValue] = value
    }
    return result
}

func fromArchivedDictionaryWithEnumerationKeys<E: EnumType, T>(dictionary: Dictionary<E.RawType, T>) -> Dictionary<E, T>? {
    var result = Dictionary<E, T>()
    for (key, value) in dictionary {
        if let enumKey = E(rawValue: key) {
            result[enumKey] = value
        } else {
            return nil
        }
    }
    return result
}

let dict = toArchivableDictionaryWithEnumerationKeys([Hello.Option1: "Bob"])
let data = NSKeyedArchiver.archivedDataWithRootObject(dict)
let value = NSKeyedUnarchiver.unarchiveObjectWithData(data) as Dictionary<String, String>
if let unarchived: Dictionary<Hello, String> = fromArchivedDictionaryWithEnumerationKeys(value) {
    // Blah blah
}

此外,您应该调用枚举HelloOptions而不是helloOptions,并调用枚举值Option1,而不是option1。 Swift中的所有类型都应该大写。你会注意到Swift的设计者虔诚地遵循了这个惯例。你也应该这样做。