NS Coding Save and Load

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • NS Coding Save and Load

    Hallo Alle zusammen,

    ich möchte mich an NSCoding heranmachen, um Daten zu speichern - genau genommen Klassen Objekte.

    Dazu habe ich ein Klassenobjekt erstellt, weiß aber ab hier nicht genau, wie es weitergehen soll.
    Im Prinzip habe ich 3 Textfelder, die die entsprechende Information liefern. Mittels Save Button soll die Information gespeichert und mittels Load Button wieder geholt werden.

    Quellcode

    1. class Person: NSObject {
    2. var Name: String
    3. var Nachname: String
    4. var Beruf: String
    5. init(Name: String, Nachname: String, Beruf: String){
    6. self.Name = Depotnummer
    7. self.Nachname = Name
    8. self.Beruf = Wein
    9. super.init()
    10. }
    11. }
    Alles anzeigen
    Die Frage, die ich mir jetzt stelle, ist wo und wie wird die Information gespeichert? Muss ich das irgendwo eintragen?
    Gibt es eine NS Methode für save und load?

    Danke schonmal.
    Krusel
  • little_pixel schrieb:

    Bei so trivialen Fällen bietet sich NSDictionary mit -writeToFile:… an.
    Auch nicht viel einfacher als NSCoding. Ob ich jetzt eine Methode names "initWithPersistentDictionary" und "persistentDictionary" schreibe und das Dictionary anschliessend auf Platte bügle oder ob ich "initWithCoder" und "encodeWithCoder" implementiere und das dann mit

    Quellcode

    1. let myObject : MyObject = NSKeyedUnarchiver.unarchiveObjectWithFile(filename) as! MyObject
    von der Platte lese schenkt sich nix. Sauberer ist m.E. die Verwendung von NSCoding.

    In dem Zusammenhang: Bei NSCoding und Swift muss man aufpassen, weil defaultmäßig sowas wie full-qualifified-classnames verwendet werden und damit das Archiv nur noch mit einem Executable desselben Targets gelesen werden kann. Das ist oft unerwünscht.
  • Super. Danke für die Antworten.
    Ich hänge gerade daran, Dateien in einem Directory zu erstellen.

    Quellcode

    1. let dirs = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.ApplicationSupportDirectory, NSSearchPathDomainMask.UserDomainMask, true)[0] as String
    2. let path = dirs.stringByAppendingPathExtension("personen.csv")
    Hier sagt er allerdings: "stringByAppendingPathExtension is unavailable: Use URLByAppendingPathExtension on NSURL instead"

    Ich nehme mal an, dass die Schreibweise überholt ist, weshalb ich folgendes versuchen wollte. Mir aber nicht sicher bin, ob ich damit richtig liege.


    Quellcode

    1. let path = NSURL(fileURLWithPath: dirs).URLByAppendingPathComponent("Data.csv")


    Ich arbeite zum ersten mal mit persistent storage ...
  • Hier sagt er allerdings: "stringByAppendingPathExtension is unavailable: Use URLByAppendingPathExtension on NSURL instead"

    Ich nehme mal an, dass die Schreibweise überholt ist, weshalb ich folgendes versuchen wollte. Mir aber nicht sicher bin, ob ich damit richtig liege.

    Die Verwendung von -stringByAppendingPathExtension: ist nicht korrekt. Wenn dann ist es -stringByAppendingPathComponent:
    Das ist aber nicht der Fehler. Irgendwo muss angeben sein, dass Du mit NSURL arbeitest, aber NSSearchPathForDirectoriesInDomains gibt eine Liste von Pfaden in Text zurück.
    Siehe z.B. auch -URLsForDirectory:…

    Du solltest Dich über den Unterschied von NSURL und NSString informieren.
    Das hat nichts mit alter Schreibweise zutun.

    Viele Grüße
  • Ok Danke an Alle. Ich bin jetzt einen Schritt weiter gekommen und habe jeweils eine save, load und path function geschrieben.

    Quellcode

    1. class Personen: NSObject, NSCoding {
    2. var Name: String
    3. var Beruf: String
    4. var Stadt: String
    5. init(Name: String, Beruf: String, Stadt: String){
    6. self.Name = Name
    7. self.Beruf = Beruf
    8. self.Stadt = Stadt
    9. }
    10. required init? (coder aDecoder: NSCoder) {
    11. Name = aDecoder.decodeObjectForKey("Name") as! String
    12. Beruf = aDecoder.decodeObjectForKey("Beruf") as! String
    13. Stadt = aDecoder.decodeObjectForKey("Stadt") as! String
    14. }
    15. func encodeWithCoder(aCoder: NSCoder) {
    16. aCoder.encodeObject(Name, forKey: "Name")
    17. aCoder.encodeObject(Beruf, forKey: "Beruf")
    18. aCoder.encodeObject(Stadt, forKey: "Stadt")
    19. }
    20. static func saveArraytoFile (data:[Personen]){
    21. if data.count==0 { return }
    22. if let path = getPath () {
    23. NSKeyedArchiver.archiveRootObject(data, toFile: path)
    24. }
    25. }
    26. static func readArrayFromFile () -> [Personen] {
    27. if let path = getPath () {
    28. if let result = NSKeyedUnarchiver.unarchiveObjectWithFile(path) as? [Personen] {
    29. return result
    30. }
    31. }
    32. return [Personen]()
    33. }
    34. private static func getPath() -> String? {
    35. let pfd = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)
    36. if let path = pfd.first {
    37. return path + "/Personen.bin"
    38. }else{
    39. return nil
    40. }
    41. }
    42. }
    Alles anzeigen

    Und ausgeführt über:



    Quellcode

    1. var Speichern = [Boxes.init(Name: "Test", Beruf: "Tester", Stadt: "Testaloniki"]
    2. Personen.saveArraytoFile(Speichern)
    3. var Laden = Peronen.readArrayFromFile()


    Jetzt eine letzte Frage - Wenn ich mir die variable "Laden" über print () ausgeben lassen möchte, bekomme ich da nur folgenden Kauderwelsch

    [<Kontakt.Personen: 0x7b6fb360>]

    Woran liegt das? Und wie behebe ich das?

    Danke schonmal.
  • Krusel schrieb:

    Mir ist gerade aufgefallen, dass mir ein Array zurückgeliefert wird, dass nur ein Element hat (also [0] ) und in diesem stehen alle Informationen.
    Sozusagen: Array [0] = [Name, Beruf, Stadt]

    Liegt das an der description oder ist das immer so?
    Das hat weder mit description etwas zu tun noch ist das halt so.

    Das liegt an Deinem komischen Code. Wenn Du ein Array speichern willst und es folgerichtig als Array wieder ausliest, dann kriegst Du auch ein Array zurück.

    Wieso das hier? Ein Array bestehend aus einem 'Boxes' Element wird mittels einer Klassenmethode der Klasse 'Personen' (warum Mehrzal?) gespeichert???

    Krusel schrieb:


    Quellcode

    1. var Speichern = [Boxes.init(Name: "Test", Beruf: "Tester", Stadt: "Testaloniki"]
    2. Personen.saveArraytoFile(Speichern)
    3. var Laden = Peronen.readArrayFromFile()
    Das iPhone sagt: "Zum Antworten streichen". Wie? Echt Jetzt? Muß ich erst die Wohnung streichen!?
  • Krusel schrieb:

    Mir ist gerade aufgefallen, dass mir ein Array zurückgeliefert wird, dass nur ein Element hat (also [0] ) und in diesem stehen alle Informationen.
    Wie ist dir das aufgefallen? Hast du mal das Array nach seiner Größe befragt (count)?

    Krusel schrieb:

    Liegt das an der description oder ist das immer so?
    Wenn du das zurückgegebene Array einfach mit print() ausgibst, wird die Description der im Array enthaltenen Elemente durch Komma getrennt ausgegeben.

    Übrigens, ich würde eine Klasse, die die Daten zu einer Person speichert, nicht Personen nennen.
  • @Michael: Wie ist dir das aufgefallen? Hast du mal das Array nach seiner Größe befragt (count)?

    Genau. Ich habe die Count Funktion benutzt und 1 als Ergebnis bekommen.
    Sprich, also ein Array mit nur einem Element [0] und darin waren dann die Informationen Name, Beruf, Stadt gespeichert.
    Ich war irgendwie davon ausgegangen, dass jeder Eigenschaft eine eigene Position im Array zugeordnet wird. Also [0] Name [1] Beruf [2] Stadt.

    @torquato: Wieso das hier? Ein Array bestehend aus einem 'Boxes' Element wird mittels einer Klassenmethode der Klasse 'Personen' (warum Mehrzal?) gespeichert?

    In Zukunft werde ich auf den Plural verzichten.

    Das mit den Boxes und Personen, war ein versehen. Ich habe den Code etwas umgeschrieben, da er sonst sehr lang ist. Ich dachte er sei so etwas anschaulicher für andere Leser, weshalb mir dann ein Schreibfehler unterlaufen ist. Boxes muss Personen bzw. Person heißen.
  • Krusel schrieb:

    Genau. Ich habe die Count Funktion benutzt und 1 als Ergebnis bekommen.
    Sprich, also ein Array mit nur einem Element [0] und darin waren dann die Informationen Name, Beruf, Stadt gespeichert.
    Dann hast du auch nur eine Person ins Array hinein getan.

    Krusel schrieb:

    Ich war irgendwie davon ausgegangen, dass jeder Eigenschaft eine eigene Position im Array zugeordnet wird. Also [0] Name [1] Beruf [2] Stadt.
    Warum sollte ein Array das tun? Dann würde ja das Array dein Person-Objekt auflösen und in drei Strings zerlegen.

    Krusel schrieb:

    Das mit den Boxes und Personen, war ein versehen. Ich habe den Code etwas umgeschrieben, da er sonst sehr lang ist. Ich dachte er sei so etwas anschaulicher für andere Leser, weshalb mir dann ein Schreibfehler unterlaufen ist. Boxes muss Personen bzw. Person heißen.
    Die init-Methoden in Swift ruft man so aber nicht auf. Um eine Instanz von deiner Person-Klasse zu erstellen schreibst du

    let person = Person(Name: "Test", Beruf: "Tester", Stadt: "Testaloniki")
  • Krusel schrieb:

    @Michael: Wie ist dir das aufgefallen? Hast du mal das Array nach seiner Größe befragt (count)?

    Genau. Ich habe die Count Funktion benutzt und 1 als Ergebnis bekommen.
    Sprich, also ein Array mit nur einem Element [0] und darin waren dann die Informationen Name, Beruf, Stadt gespeichert.
    Ich war irgendwie davon ausgegangen, dass jeder Eigenschaft eine eigene Position im Array zugeordnet wird. Also [0] Name [1] Beruf [2] Stadt.

    Du speicherst ein Array mit Objekten vom Typ Person, nicht ein Array der Properties dieses Objektes. Da Du StringLiteralConvertible implementiert hast, wird dieses eine Objekt dann halt auch wie angegeben mit "Name, Stadt, Beruf" angezeigt und nicht mehr wie vorher von NSObject übernommen bloß mit der Speicheradresse.
    Das iPhone sagt: "Zum Antworten streichen". Wie? Echt Jetzt? Muß ich erst die Wohnung streichen!?
  • @troquato: Du speicherst ein Array mit Objekten vom Typ Person, nicht ein Array der Properties dieses Objektes.

    Jetzt verstehe ich. Nehmen wir an, ich würde jetzt gerne ein Array speichern.

    Also ar = [1,2,3,4,5]

    Könnte ich das auch über meine saveArraytoFile Funktion machen?
    Also in etwa so?

    1. func saveArraytoFile (data:[Hier Array Einfügen]){
    2. if data.count==0 { return }
    3. if let path = getPath () {
    4. NSKeyedArchiver.archiveRootObject(data, toFile: path)
    5. }
    6. }
  • Krusel schrieb:



    Nehmen wir an, ich würde jetzt gerne ein Array speichern.

    Könnte ich das auch über meine saveArraytoFile Funktion machen?
    Also in etwa so?

    func saveArraytoFile (data:[Hier Array Einfügen]){

    Probier es aus!

    Es besteht die Möglichkeit, daß Array<Person> nicht zum Typ Array<Array<Person>> paßt. Nur so eine Verfmutung. *Schulterzuck*

    Krusel schrieb:


    if data.count==0 { return }

    -> guard data.count > 0 else { return }

    Krusel schrieb:


    if let path = getPath () {

    1.) Halte den Atem an, wenn Du in Zukunft eine Funktion 'get...' benennst.
    2.) Warum eine Funktion und keine Property?
    3.) Warum ist das überhaupt ein Teil von 'Person'? Wieso soll 'Person' wissen, wo es selbst gespeichert wird?
    Das iPhone sagt: "Zum Antworten streichen". Wie? Echt Jetzt? Muß ich erst die Wohnung streichen!?