I have a struct called trip:
struct trip {
var name: String
var description: String
var elements: [elementType] = []
}
elementType is a type declared in protocol.
Then I've declared an array called trips:
var trips: [trip] = []
The problem is that I have to save trips array to be able to show items after closing the app. First of all, I tried to use NSUserDefaults but it can save only few types and Any (type of struct) isn't one of them.
How can I save and restore this array?
You can only save NSData, NSString, NSNumber, NSDate, NSArray, and NSDictionary types in NSUserDefaults.
So you can add a init method inside the struct so that the data being created can be encoded and then stored in NSUserDefaults.
Follow the answer to this question: How to save struct to NSUserDefaults in Swift 2.0
Related
Right now I have a struct with multiple dictionaries and string that holds the user's score for each level and the user's name that they type. I then save the struct scores into an NSUserdefault.
struct Scores: Codable {
var userName: String = ""
var totalScore: Int = 0
var highScore: [String : Int] = [:]
var scoreA: [String : Int] = [:]
var scoreB: [String : Int] = [:]
}
UserDefaults.standard.set(try? PropertyListEncoder().encode(scores), forKey:"scores_1")
This works well but I will need to save the user's last ten scores. I am wondering if I should use core-data or keep using NSUserdefaults? Not sure which is best practice.
Edit: Should I save the data in a .json file?
UserDefaults is best used to store small amounts of data, and not arrays.
Every time you call the key, the entire plist file that it's stored in is called into memory.
eg)
let volumeLevel = UserDefaults.Standard.integer(forKey: "volume")
So if you are storing an array that grows every time the user plays, eventually you will have memory problems.
With the example you have above, using UserDefaults to store High Score and UserName is fine, but I would recommend using CoreData (or something else) to store an array that has data for each run of the game.
Is it possible in Swift to create a struct that has "dynamic" properties?
i.e. if I have a dictionary that is returned from some JSON API and I know at build time that it has name, id in it.
Then I can build a struct like...
struct MyStruct {
let name: String
let id: String
}
But then if the dictionary has a custom attribute like age... can I do something to add a typed property to the struct at run time?
I know (think) this sort of thing was possible with Objective-C but there was a lot more runtime control.
Is it possible in Swift?
Thanks
Simply add a variable to your class that is optional, as follows:
var age: Int?
Hope that helps
I have an array of classes, which looks like this:
var myItems = [myClass]()
class myClass: NSObject {
var a: String?
var b: String?
var c: String?
var d: String?
}
What I want is to save the array called myItems into my database, and have every class inside of a personal section inside the database. Basically, I want every class to look like the one called "Eko" in this image:
To clarify, after "Eko" all the rest of the classes which is inside of the array myItems should be displayed. To achieve what the picture is demonstrating, I used this code:
let data = self.myItems[0]
let currU = FIRAuth.auth()?.currentUser?.uid
let userRef = self.ref.child("users").child(currU!).child(data.a!)
userRef.updateChildValues(["a": data.a!, "b": data.b!, "c": data.c!, "d": data.d!])
Obviously, this will only save the class at index 0 from the array myItems into the Firebase Database, which is displayed in the image above.
My question is thus, how do I save the entire array into the database? With my code I can only save 1 class from the array, and I would like to save all of the items into the database, so that they end up looking the same way that the one class does in the image. You could compare this to populating a tableView, where you need the "indexPath.row" to populate it with all the items instead of only one. I hope that I was clear enough!
You can't save a class into Firebase. But.. A class has a similar structure to a dictionary (properties and values, like key: value pairs etc).
Arrays in Firebase should generally be avoided - they have limited functionality and the individual elements cannot be accessed and for any changes you have to re-write the entire array.
Using a structure where the parent key names are created with childByAutoId is usually preferred.
The easiest solution is to simply add intelligence to the class so it would craft a dictionary and then save itself.
Craft a user class
UserClass
var name = String()
var food = String()
func saveToFirebase() {
let usersRef = myFirebase.child(users)
let dict = ["name": self.myName, "food", self.myFood]
let thisUserRef = usersRef.childByAutoId()
thisUserRef.setValue(dict)
}
}
and and array to store them
var usersArray = [Users]()
populate the array
var aUser = UserClass()
aUser.name = "Leroy"
aUser.food = "Pizza"
usersArray.append(aUser)
var bUser = UserClass()
bUser.name = "Billy"
bUser.food = "Tacos"
usersArray.append(bUser)
and then iterate over the array saving each user
for user in usersArray {
user.saveToFirebase()
}
this will result in
users
-Ykasokokkpoad
name: Leroy
food: Pizza
-YJlaok9sk0sd
name: Billy
food: Tacos
which is very similar to the structure you want. There are many other ways of creating this structure. For example, you could craft the entire dictionary in code and write it all out at one time.
Pardon typo's, I wrote this on the fly.
Firebase has no native support for arrays. If you store an array, it really gets stored as an "object" with integers as the key names.
// we send this
['hello', 'world']
// Firebase stores this
{0: 'hello', 1: 'world'}
Read this post for better understanding.
I need save in NSUserDefaults an array or other structure of data to save objects with this format:
name = "myName", lastName = "myLastName"
I was trying to do this with an array of arrays but this can't save in NSUserDefaults.
Now I am trying with a custom class with structure to create objects and append to the array, but also get an error when trying to save this to NSUserDefaults. I need save with this structure, but I don't know what is the correct form. How would I do this?
var taskMgr: TaskManager = TaskManager()
struct task {
var name = "Un-Named"
var lastName = "Un-lastNamed"
}
class TaskManager: NSObject {
var tasks : [task] = []
func addTask(name : String, lastName: String){
tasks.append(task(name: name, lastName: desc))
}
}
NSUserDefaults expects the stored objects to all be property list objects, i.e. instances of NSArray, NSDictionary, NSString, NSNumber, NSData, or NSDate. Your struct isn't one of those. You'll need to convert your objects to property list types before you store them. One way to do that is to use NSKeyedArchiver and the NSCoding protocol to write your structs into an instance of NSData.
I need save a variable of type:
var array1: [AnyObject!] = []
I tried this but isn't save:
var key = "keySave"
var defaults = NSUserDefaults.standardUserDefaults()
array1.append(["key1": "val1", "key2": "val2"])
array1.append(["key2": "val3", "key4": "val4"])
defaults.setObject(array1, forKey: key)
defaults.synchronize()
Need I cast this variables to other type of data? What is the correct form to make this?
Thanks!
This is not allowed. According to the documentation of NSUserDefaults class, only these specific types are supported by setObject:forKey: method:
The value parameter can be only property list objects: NSData, NSString, NSNumber, NSDate, NSArray, or NSDictionary. For NSArray and NSDictionary objects, their contents must be property list objects.
You can fix this by replacing a Swift array with NSMutableArray, a subclass of the allowed NSArray class.