2016-05-18 11 views
0

私が読んで試したように、私は単純なデータ型をpListファイルに保存することしかできません。それにもかかわらず、私はデータを表現するために構造体、クラスなどを使用するのが好きです。これは、pListファイルにできるだけ簡単に保存し、リロードしなければなりません。Swift: "複雑な"データを持つ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() 
    } 
} 
+0

あなたの複雑さに応じて、それがより適切な適合であるかどうかを見るために 'CoreData'をチェックアウトする価値があるかもしれません。 – Alexander

+0

失敗することができない場合は、 'init'を必要としません。そのため、 'struct'に' init'メソッドが定義されていない場合は、メンバーワイズ初期化を行うデフォルトの 'init'があります。したがって、 'SteeringItem'の' struct'に 'init'メソッドは必要ありません。 – ColGraff

答えて

1

これを行うには、いくつかの方法があります、あなたはNSCodingプロトコルに準拠したり、辞書にあなたのクラス/構造体を変換する方法を記述してシリアライズすることができますそこから。

ここには、NSCoding protocolを使用するための良いイントロがあります。

ディクショナリとの変換に関しては、一般的な方法はDictionary<String, AnyObject>を使用して、キー:値のペアをメンバー変数に検証してコピーするfuzz initメソッドを提供することです。 initと同じキー:値のペアを持つDictionary<String, AnyObject>を返すメソッドも用意します。次に、createメソッドを呼び出して結果のDictionaryをシリアル化してシリアル化することができます。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)) 
+0

うわー!私はそんなに学んだ。今私はクラスを救うことができました。次に、私がそれをリロードできるかどうかを確認します。 :-) どうもありがとうございました! – Peter71

+0

1つの質問:クラスを元に戻すにはどうすればよいですか?通常、私は "dict.objectForKey(" myVar ")!= nil {myVar = d.objectForKey(" myVar ")!as![String]}"を使用しますが、これは失敗します。これは、次のようにキャストする必要があります: "myVar = MyClass(dict:dict as![String:AnyObject])!" ? – Peter71

+0

「Dictionary」 – ColGraff

関連する問題