Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Save struct in class to NSUserDefaults using Swift

I have a class and inside the class is a (swift) array, based on a global struct. I want to save an array with this class to NSUserDefaults. This is my code:

struct mystruct {
    var start : NSDate = NSDate()
    var stop : NSDate = NSDate()
}

class MyClass : NSObject {

    var mystructs : [mystruct]

    init(mystructs : [mystruct]) {

        self.mystructs = mystructs 
        super.init()
    }

    func encodeWithCoder(encoder: NSCoder) {
        //let val = mystructs.map { $0 as NSObject } //this also doesn't work
        let objctvtmrec = NSMutableArray(mystructs)  //gives error
        encoder.encodeObject(objctvtmrec)
        //first approach:
        encoder.encodeObject(mystructs) //error: [mystructs] doesn't conform to protocol 'anyobject'
    }

}

var records : [MyClass] {
    get {
        var returnValue : [MyClass]? = NSUserDefaults.standardUserDefaults().objectForKey("records") as? [MyClass]
        if returnValue == nil
        {
            returnValue = []
        }
        return returnValue!
    }
    set (newValue) {
        let val = newValue.map { $0 as AnyObject }
        NSUserDefaults.standardUserDefaults().setObject(val, forKey: "records")
        NSUserDefaults.standardUserDefaults().synchronize()
    }
}

I already subclassed to NSObject, and I know I need NSCoding. But I don't find any way to convert the struct array to an NSMuteableArray or something similar I can store. The only idea until now is to go through each entry and copy it directly to a new array or to use much or objective-c code all over the project, so i never need to convert from swift arrays to objective-c arrays. Both are things I don't want to do.

like image 752
Thomas Avatar asked Aug 28 '14 10:08

Thomas


People also ask

How do I save an array of objects in Swift?

You'll need to convert the object to and from an NSData instance using NSKeyedArchiver and NSKeyedUnarchiver . For example: func savePlaces(){ let placesArray = [Place(lat: 123, lng: 123, name: "hi")] let placesData = NSKeyedArchiver. archivedDataWithRootObject(placesArray) NSUserDefaults.

What is NSUserDefaults in Swift?

Overview. The NSUserDefaults class provides a programmatic interface for interacting with the defaults system. The defaults system allows an app to customize its behavior to match a user's preferences. For example, you can allow users to specify their preferred units of measurement or media playback speed.

What is nsuserdefaults in Swift?

NSUserDefaults is ideal for storing small bits of information between app launches. Its API is very simple, and does its job well. It does show its Objective-C roots in Swift moreso than some other classes, but it still gets the job done.

What is an instance of a Swift class?

In Swift, you define a structure or class in a single file, and the external interface to that class or structure is automatically made available for other code to use. An instance of a class is traditionally known as an object.

What is the difference between nsuserdefaults and NSData?

Just to make it clear, since they only differ by one letter, the first one listed as NSDat a, while the fourth one is an NSDat e. A property list, or NSUserDefaults can store any type of object that can be converted to an NSData object. It would require any custom class to implement that capability, but if it does, that can be stored as an NSData.

What is the difference between a struct and a class in Swift?

Structures and classes have a similar definition syntax. You introduce structures with the struct keyword and classes with the class keyword. Both place their entire definition within a pair of braces: Whenever you define a new structure or class, you define a new Swift type.


1 Answers

Swift structs are not classes, therefore they don't conform to AnyObject protocol. You have to rethink your approach. Here are some suggestions:

  1. Convert your struct to final class to enforce immutability

    final class MyStruct {
        let start : NSDate = NSDate()
        let stop : NSDate = NSDate()
    }
    
    encoder.encodeObject(mystructs)
    
  2. Map them as an array dictionaries of type [String: NSDate]

    let structDicts = mystructs.map { ["start": $0.start, "stop": $0.stop] }
    encoder.encodeObject(structDicts)
    
like image 111
akashivskyy Avatar answered Oct 21 '22 06:10

akashivskyy