Swift:pList with" complex"数据

时间:2016-05-18 13:06:29

标签: swift save plist nsdata

当我阅读并试用:-)我只能在pList文件中保存一些简单的数据类型。不过我喜欢使用结构,类等来表示我的数据。这应该尽可能容易地保存到pList文件中并重新加载。

我知道,NSData是pLists的有效类型。而且,这是一般数据类型。因此,将结构或类变量移动/转换/强制转换为要保存和重新加载的NSData对象是个好主意?怎么做?

直到现在我使用这样的东西来保存:

let dict: NSMutableDictionary = ["XYZ": "XYZ"]

// saving values
dict.setObject(myBasicArray, forKey: "BasicArray")

dict.writeToFile(path, atomically: false)

更新 我使用提供的代码并将其扩展为处理结构:

import Cocoa

struct SteeringItem {
    var ext    = String()   // extension including dot e.g. ".JPG"
    var bitmap = Int()      // flag for grouping file types, e.g. photos

    init?(ext: String, bitmap: Int) {
        // Initialize stored properties.
        self.ext    = ext
        self.bitmap = bitmap
    }
}

class Foo {
    let one: Int
    let two: SteeringItem


    init(one:Int, two: SteeringItem) {
        self.one = one
        self.two = two
    }

    init?(dict:[String: AnyObject]) {
        guard let
            one = dict["one"] as? Int,
            two = dict["two"] as? SteeringItem else { return nil }

        self.one = one
        self.two = two
    }

    func toDictionary() -> [String: AnyObject] {
        var retval = [String: AnyObject]()
        if let
            one = self.one as? AnyObject,
            two = self.two as? AnyObject {
            retval["one"] = one
            retval["two"] = two
        }
        return retval
    }
}

// create struct
let writeStruct = Foo(one: 1, two: SteeringItem(ext: "one",bitmap: 1)!)
print(writeStruct, "\n")

// write to plist
let writeDict = writeStruct.toDictionary() as NSDictionary
let path = ("~/test.plist" as NSString).stringByExpandingTildeInPath
writeDict.writeToFile(path, atomically: true)

// print contents of file
print(try NSString(contentsOfFile: path, encoding: NSUTF8StringEncoding))

// read plist and recreate struct
if let
    readDict = NSDictionary(contentsOfFile: path) as? [String:AnyObject],
    readStruct = Foo(dict: readDict) {
    print(readStruct)
}

但这不再写了。使用String,它使用" struct SteeringItem"它没有!

更新2:类而不是结构

    class SteeringItem : NSObject, NSCoding {
    var ext    = String()   // extension including dot e.g. ".JPG"
    var bitmap = Int()      // flag for grouping file types, e.g. photos

    func encodeWithCoder(aCoder: NSCoder) {
        aCoder.encodeObject(ext,    forKey: "ext")
        aCoder.encodeObject(bitmap, forKey: "bitmap")
    }

    required convenience init?(coder aDecoder: NSCoder) {
        let ext    = aDecoder.decodeObjectForKey("ext")    as! String
        let bitmap = aDecoder.decodeObjectForKey("bitmap") as! Int

        self.init(ext: ext, bitmap: bitmap)
    }

    init?(ext: String, bitmap: Int) {
        // Initialize stored properties.
        self.ext    = ext
        self.bitmap = bitmap

        super.init()
    }
}

1 个答案:

答案 0 :(得分:1)

有几种方法可以执行此操作,您可以遵循NSCoding协议,也可以编写方法将类/结构转换为字典并从那里进行序列化。

这是使用NSCoding protocol的好介绍。

对于转换为Dictionary和从Dictionary转换,通常的方法是提供一个可用的init方法,该方法使用Dictionary<String, AnyObject>验证并将key:value对复制到成员变量。您还提供了一个方法,该方法返回Dictionary<String, AnyObject>,其中init具有与Dictionary相同的键:值对。然后,您可以通过调用create方法并序列化生成的Dictionary来序列化,通过读入init并将其传递给/// Provides conversion to and from [String: AnyObject] for use in serialization protocol Serializable { init?(dict:[String: AnyObject]) func toDictionary() -> [String: AnyObject] } struct SteeringItem { // Changed var to let, it's a good practice with a simple struct let ext : String // extension including dot e.g. ".JPG" let bitmap : Int // flag for grouping file types, e.g. photos } struct Foo { let one: Int let two: SteeringItem } // Add serialization to structs extension SteeringItem: Serializable { init?(dict:[String: AnyObject]) { guard let ext = dict["ext"] as? String, bitmap = dict["bitmap"] as? Int else { return nil } self.ext = ext self.bitmap = bitmap } func toDictionary() -> [String: AnyObject] { var retval = [String: AnyObject]() if let ext = self.ext as? AnyObject, bitmap = self.bitmap as? AnyObject { retval["ext"] = ext retval["bitmap"] = bitmap } return retval } } extension Foo: Serializable { init?(dict:[String: AnyObject]) { guard let one = dict["one"] as? Int, twoDict = dict["two"] as? [String: AnyObject], two = SteeringItem(dict: twoDict) else { return nil } self.one = one self.two = two } func toDictionary() -> [String: AnyObject] { var retval = [String: AnyObject]() let twoDict = self.two.toDictionary() if let one = self.one as? AnyObject, two = twoDict as? AnyObject { retval["one"] = one retval["two"] = two } return retval } } 方法进行反序列化。

以下是转化的一个例子:

import Foundation

// create struct
let writeStruct = Foo(one: 1, two: SteeringItem(ext: "jpg", bitmap: 1))
print(writeStruct, "\n")

// write to plist
let writeDict = writeStruct.toDictionary() as NSDictionary
let path = ("~/test.plist" as NSString).stringByExpandingTildeInPath
writeDict.writeToFile(path, atomically: true)

// print contents of file
print(try NSString(contentsOfFile: path, encoding: NSUTF8StringEncoding))

// read plist and recreate struct
if let
  readDict = NSDictionary(contentsOfFile: path) as? [String:AnyObject],
  readStruct = Foo(dict: readDict) {
  print(readStruct)
}

以下是如何测试它(在操场上):

Foo(one: 1, two: SteeringItem(ext: "jpg", bitmap: 1)) 

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>one</key>
    <integer>1</integer>
    <key>two</key>
    <dict>
        <key>bitmap</key>
        <integer>1</integer>
        <key>ext</key>
        <string>jpg</string>
    </dict>
</dict>
</plist>

Foo(one: 1, two: SteeringItem(ext: "jpg", bitmap: 1))

结果:

All