iOS - Locally saving an array of key value pairs

杀马特。学长 韩版系。学妹 提交于 2019-12-13 02:38:34

问题


In an app I'm developing the user needs to add an "enterprise" to use the app. However, they can add more than one "enterprise" to the app. Every enterprise added needs two things: a name, and an enterprise API key.

I have created an "Enterprise" class:

class Enterprise : NSObject {

    var name:String!
    var apiKey:String!

    init (name:String, apiKey:String) {
        self.name = name
        self.apiKey = apiKey
    }

    required init(coder decoder: NSCoder) {
        self.name = decoder.decodeObjectForKey("name") as String
        self.apiKey = decoder.decodeObjectForKey("apiKey") as String
        super.init()
    }

    func encodeWithCoder(coder: NSCoder) {
        coder.encodeObject(self.name, forKey: "name")
        coder.encodeObject(self.apiKey, forKey: "apiKey")
    }

}

One thing to note about this class, in the example I followed to build this class they have sub-classed the class as NSCoder as well as NSObject, however if I added "NSCoder" to the class, I get the following error:

Multiple inheritance from classes 'NSObject' and 'NSCoder'

When saving the array I'm using the following:

let name = self.enterpriseName.text
let key = self.apiKey.text
if name != "" {
    if key != "" {
        let defaults = NSUserDefaults.standardUserDefaults()
        let objectKey = "enterprise"
        var ent = [Enterprise(name: name, apiKey: key)]
        var entData = NSKeyedArchiver.archivedDataWithRootObject(ent)
        defaults.setObject(entData, forKey: objectKey)
        defaults.synchronize()
    }
    else {
        println("No API key")
    }
}
else {
    println("No name")
}

This seems to work when storing one value, but when I check how many items are in the array at launch, it only shows 1.

Any ideas how I can do this? The end result I'm looking for would be something like:

Enterprises:
    Enterprise
        name: abc
        apiKey: 184nfh692j6j31))8dx

    Enterprise
        name: def
        apiKey: 23oih9823tng893g2gd

    Enterprise:
        name: ghi
        apiKey: sfgYSS4yw44gw31!#%q

With the ability to remove a particular enterprise from the list if the user choose to delete it.

EDIT

Here's what worked, using Leonardo's (below, and accepted answer) method:

let name = self.enterpriseName.text
let apiKey = self.apiKey.text
if name != "" {
    if apiKey != "" {
        var enterprises = NSMutableDictionary()
        var loadedEnterprises = Load.dictionary("enterprises")
        if loadedEnterprises != nil {
            if(loadedEnterprises.count > 0) {
                for (key, value) in loadedEnterprises {
                    enterprises.setObject(value, forKey: key as String)
                }
            }
        }
        enterprises.setObject(apiKey, forKey: name)     
        Save.dictionary("enterprises", enterprises)
    }
    else {
        println("No API key")
    }
}
else {
    println("No name")
}

回答1:


You should use a Dictionary otherwise you may end up with the same enterprise with different keys. I have created a class to load and save dictionaries to the user default. You should do as follow:

class Load {
    class func dictionary(key:String) -> NSDictionary! {
        return NSUserDefaults.standardUserDefaults().objectForKey(key) as? NSDictionary
    }
}

class Save {
    class func dictionary(key:String, _ value:NSDictionary) {
        NSUserDefaults.standardUserDefaults().setObject(value, forKey: key)
    }
}

class Remove {
    class func object(key:String) {
        NSUserDefaults.standardUserDefaults().removeObjectForKey(key)
    }
}


var enterprises:[String:String] = ["abc":"184nfh692j6j31))8dx","def":"23oih9823tng893g2gd","ghi":"sfgYSS4yw44gw31!#%q"]
Save.dictionary("enterprises", enterprises)

name = "jkl"
apiKey = "9a4giNifjKJq6v8G4fb"

if !name.isEmpty {
    if !apiKey.isEmpty {
        enterprises[name] = apiKey
        Save.dictionary("enterprises", enterprises)
    } else {
        println("No API key")
    }
} else {
    println("No name")
}

for (key, value) in enterprises {
    println("\(key)=\(value)")
}

let loadedDictionary = Load.dictionary("enterprises")

for (key, value) in loadedDictionary {
    println("\(key)=\(value)")
}



回答2:


You always override 'Enterprise" for 'enterprise' Key, use an array:

var entArray = defaults.objectForKey(objectKey)
entArray?.addObject(entData)
defaults.setObject(entArray, forKey: objectKey)

EDIT:

works for me, but it's not good solution:

func getEnterprise() {
    let objectKey = "enterprise"
    // get stored array
    let defaults = NSUserDefaults.standardUserDefaults()
    var array = defaults.objectForKey(objectKey) as? Array<NSData>
    if array != nil {
        for data in array! {
            var enterprise = NSKeyedUnarchiver.unarchiveObjectWithData(data) as? Enterprise
            println("\(enterprise!.name)")
        }
    }
}

func saveEnterprise() {
    let name = self.enterpriseName
    let key = self.apiKey
    if name != "" && name != nil {
        if key != "" && key != nil {
            let defaults = NSUserDefaults.standardUserDefaults()
            let objectKey = "enterprise"
            var ent = Enterprise(name: name!, apiKey: key!)

            // get stored array
            var array = defaults.objectForKey(objectKey) as? Array<NSData>
            if array == nil {
                array = Array()
            }
            var entData = NSKeyedArchiver.archivedDataWithRootObject(ent)
            array?.append(entData)
            defaults.setObject(array, forKey: objectKey)
            defaults.synchronize()
        }
        else {
            println("No API key")
        }
    }
    else {
        println("No name")
    }
}


来源:https://stackoverflow.com/questions/28481299/ios-locally-saving-an-array-of-key-value-pairs

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!