1

I'm trying to implement the NSCoder, but am currently facing a stubborn issue. My goal is to save the array of strings via NSCoder to a local file and load it when the app opens next time.

Here is the class i've created, but i'm not sure how i should handle the init and encoder functions:

class MyObject: NSObject, NSCoding {

var storyPoints: [String] = []

init(storyPoints : [String]) {
    self.storePoints = storePoints
}


required init(coder decoder: NSCoder) {
    super.init()

???

}

func encodeWithCoder(coder: NSCoder) {
???
}

}

Moreover, how do i access it in my view controller? where should i declare a path for saving the NSCoder? It's not really clear enough.

Looking forward to any advices.

Thank you.

David Robertson
  • 1,561
  • 4
  • 19
  • 41
  • take a look at the link http://www.raywenderlich.com/12779/icloud-and-uidocument-beyond-the-basics-part-1 to get clear picture about persisiting user data with the help of NSCoder and NSKeyedArcheiver – vignesh kumar Sep 11 '15 at 15:01

1 Answers1

2

Here is an implementation and a playground example that saves the object to the /tmp directory. The init(coder:) function overrides NSObject's so is required and since it is not a designated initializer it must be marked as convenience. Also because init(coder:) is a convenience initializer, it can not call super.init().

To directly answer your question about archiving an array, just type cast the result from decoderObjectForKey(_:). Check the NSCoding documentation for information and API's to code/decode. There is a lot there.

import Cocoa

class MyObject: NSObject, NSCoding {

  var storyPoints: [String] = []

  init(storyPoints : [String]) {
    self.storyPoints = storyPoints
  }

  convenience required init(coder decoder: NSCoder) {
    let storyPoints = decoder.decodeObjectForKey("storypoints") as! [String]
    self.init(storyPoints: storyPoints)
  }

  func encodeWithCoder(coder: NSCoder) {
    coder.encodeObject(storyPoints, forKey: "storypoints")
  }
}

enter image description here

Price Ringo
  • 3,424
  • 1
  • 19
  • 33
  • Thank you! Works nicely, but each time i run the app the array values are reassigned as if no changes happened. – David Robertson Sep 11 '15 at 15:19
  • Can you confirm that you are calling the archiveRootObject(_:toFile:) method after the changes are made to your object? – Price Ringo Sep 11 '15 at 15:30
  • yes i'm doing it in the function code - right after the obj.storyPoints.append(newObject) happens. yet when i restart - the array is blank again. – David Robertson Sep 11 '15 at 15:44
  • there is a little difficulty, because - i can append the array either with one function or the other separately. so to access MyObject array from both functions i declared it on the top before viewDidLoad. What i don't understand is - i have to declare the NSKeyedArchiver and the rest of the code twice in two separate functions? – David Robertson Sep 11 '15 at 15:48
  • Be sure that you are using MVC best practices. Do use NSCoding for initializing and saving your model. How your view controllers access the model is important but can't be handled here in comments. Don't worry about the cost of instantiating NSKeyedArchiver/Unarchiver. It is a singleton and should be used as needed. – Price Ringo Sep 11 '15 at 16:15