I'm a software development student and for a school project me and a friend are making a iOS Swift game and we are learning Swift 3 as we progress in the game aspects.
Now, we have come to the part of the development where we question how is game data going to be saved (I'm talking about scores, player's name, in-game money, if the player plays in mute or unmute.. you know that kind of stuff)
The game uses an avatar and the player can customize it, so data customization needs to be saved too.
Right now we manage this data throught variables like
var eyeColor = "#04ff45"
var eyetype = 3 // And so on
I have done some research on this and found that there are various methods we could use.
Like, we could use Core Data or a Dictionary or a JSON file.
I'd like to know which could be the best/easiest way to acomplish this, if we need to use any specific libraries and some basic code on how to write/read the data
Thank you very much
Best way to save scores is by using NSUserDefaults
To save settings such as volume, you can follow the model I have below.
//When you tap on the mute button, execute this code.
if soundSwitch { //true
UserDefaults.standard.set(false, forKey: "SoundSwitch")
soundSwitch = false
} else { //false
UserDefaults.standard.set(true, forKey: "SoundSwitch")
soundSwitch = true
}
If you are saving players money, name and all this other stuff, it would be better to save them in some kind of database. I'm not sure if you can do that with GameCenter.
The easiest way to save data you are working with on the device would be to use NSUserDefaults. All you have to do is create a key, and store a value under that key. You can then use the key to access the value later and it is stored on the phone's permanent memory.
For example, you would use the user defaults to create a key called "eye color", store a value under that key, and then access it later using the term that you know the value is stored under (i.e. the key). This is a very simple way of storing such information.
Related
I'm having some issues with the app, that I'm making, which I thought would be a lot easier to explain with some photos, so ... :
Ofcourse the "Create New Person-button" in nr. 1 leads you to number two.
Now, I'm having issues figuring out how to save this data about the person in the "People Diary". The goal is, that when you enter a person's name, add a photo (an enable-camera feature, I will struggle with at a later time...) and add an answer to the question - then you only need to press "Save this person", and then you will be redirected to the AllPersonsInYourDiaryViewController, where there is now a new tableViewCell with this new person's name (maybe with a subtitle containing the answer and the photo shown in miniature in the cell too).
(Naturally you can then enter this cell with the data about the person too - but that comes next.)
So far in the app, I have used NSUserDefault, when allowing the user to create this specifik Diary by the Name "Antons Diary" with the specifik question and so on. But now it came to my attention, that maybe it is smarter to use something else? I tried with dictionaries, but couldn't get this to work properly.
So...: Before I spend hours and hours playing around with one of these ways, will someone smarter than me, tell me what the best approach would be?
If I can give my two cents, the first thing you have to do is to “design” how to represent a person programmatically. You can create a struct or class to do so, even though a struct is more suitable:
struct Person {
var name: String?
var answer: String?
var photo: String?
}
Then you can decide how to save the data of such an object persistently. If you want to use a database, then I would recommend using SQLite with FMDB library. It’s really easy and fast to learn how to use it, and it's also quite handy. I've used it big projects and it works smoothly. I find CoreData too complicated and an overkill based on what you need.
If you don’t want to use a database, your only other way is to save to files, but still, you’ve got options here too. If you encode (see Codable protocol in Swift), you can use NSKeyedArchiver to convert to Data object and write then to disk. If you like using dictionaries, and since the properties you’re going to have for a person are not going to be too many, you could create a dictionary by assigning the properties and their values, and then convert and save as JSON data, or even Plist files. Without any intension to do promotion here, but just to provide some additional help, if you want take a look to a library that I’ve written and that can do all these automatically for you. It’s a protocol that you have to adopt, and then you can instantly convert your struct to a dictionary, JSON or plist and save to files.
No matter which way you’re going to select, save the images as single files to documents directory, and keep their file names only stored to database/file. Based on them, you can build the path to each image (or the URL) easily when needed. Warning: Do not save the full path to the documents directory, especially if you’re testing on Simulator; paths are changing on each build. Save the file name only.
Additionally, if you’re going to use a struct like the one shown above, you could implement small but super convenient functions that will be responsible for saving, loading, or updating your data to the solution (database/file) you’ll eventually select. That way, you’ll have related stuff gathered in one place, and easily accessible (i.e., person.save()).
struct Person {
var name: String?
var answer: String?
var photo: String?
func save() {
…
}
func load() {
…
}
// More functions…
}
Lastly, avoid using UserDefaults, or at least keep just a few non-critical data there. UserDefaults are not meant to keep all data produced by your app. Most importantly, do not use it for saving sensitive data, especially passwords or other stuff like that.
I hope the above will help you make your mind.
I can give you the logic behind coreData and NSUserDefaults, but you will decide which one should be used.
CoreData is usually used as a database. you can create entities and attributes for every entity. Moreover, you can create relations between these entities.
When extracting data from coreData, you can arrange this data using NSSortDescriptor or select a specific record using NSPredicate.
So as you can see CoreData is a database.
While NSUserDefaults is usually used to save a password, username, userID... and such issues that you will regularly use in the app. NSUserDefaults gives you a direct access to the saved variables at any time. However, CoreData will take more time and lines of code to access the entity and make the query.
Now, check which method suits your case more.
I'm making a game that has skills which each have their own level and experience depending on how much they player has trained them. It also has things like money and items stored in a bank.
Where should I save these items so that you can access it from any view controller and so that it will save when you close and open the game?
I've decided to try and use the UserDefualts but I'm not sure what I'm doing wrong.
Could someone explain if I wanted to have a variable called coins and have a label that displayed these coins starting from 0 and every time a button is clicked the coins go up by 1. Then also be able to close the game or witch views and have the coins stay the same as before it was closed?
Firstly you should define if the game data is sensitive.
If it is not sensitive, try to use NSUserDefaults, it is a fast way to provide primitive storage for the data that you have described.
If it is and data should be protected, try to use more sophisticated ways like CoreData and Realm. They have a bunch of security wrappers that will not give so easy way to manage saved data.
But you also could use cool features such as iCloud, this option will give you the possibility to store and sync game data between platforms and be quite secure.
You can create a singleton and store your data there.
class GameState {
static let shared = GameState()
var items: [Items]
var balance: Int
var level: Int
var xp: Double
func save() {
// Save to CoreData
}
}
To access it from any other class:
GameState.shared.xp = 30
GameState.shared.save()
You would of course store the data in a database, but the singleton gives you a convenient access.
I have iOS app that takes data from the server as json and then serializes them into objects of different types. Types can be complicated, can contain subtypes, can inherit, so there is no any limitations. Another thing that makes everything even more complicated is some of types are stored as AnyObject? and only in run time they are being serialized into real types accordingly to the specific rules. Something like that:
class A {
var typeName: String?
var b: AnyObject?
}
Then when it's serialized it can be done something like that:
if let someClass = NSClassFromString(typeName) as? SomeGenericType.Type{
b = someClass.init()
}
Also querying should be done on all the data. Currently I'm trying to store all of them locally, then load into memory and query there from the code. I'm using User defaults, but they have some limitations, also I needed to provide custom coding to make it work, and each time when I add a new field it turned out that I missed something in coding and nothing works. So it's pain.
Ideally I would just do some magic command and all the objects are sent to local storage no matter how complicated they are. The same to extract them from this storage. Also, user change data so I can't just store primary Json. And I don't want to covert objects back to Jason as for it's pain too.
Any suggestions?
If you want to use sqlite then You can store whole object in one row! I means you can create table with 2 columns one is id and second is your dataobject(it's data type should be blob). Then convert your whole object into data. Then store in sqlite table and retrieve it as data then convert it to object when want to use. By this way your object will remains in same format as you asked
Firebase while meant for online synching and storage can also cache everything locally in case you are offline and perform query's against the local cache. It uses JSON.
CouchDB also has a mobile version for iOS.
Both of those are over kill if your dataset is small; you can just store it as a text file and read the JSON back in. See performance characteristics here. The graph is for a 7MB file so if you are significantly less than that your load time may be minimal.
NSKeyedArchiver.archivedData(withRootObject:) is great for storing custom objects as Data objects. The only thing you need to do to be able to use this is to make your custom objects conform to NSCoding. A great example can be found here:
Save custom objects into NSUserDefaults
Once you have the Data version of the object, it can easily be stored in UserDefaults, as a property in CoreData, or even in the app's keychain entries. Depending on your use case, sensitivity of data, and how much data you intend to store, you might want to use any number of storage methods. NSKeyedArchiver.archivedData(withRootObject:) allows you to pretty much use any of them.
I have my own custom data structures which receive input through the ViewController class. The interface is a simple text field, which is linked to a variable that the contents of the text field is copied to. Upon launching the app, the text field should be prepopulated with data entered in the past. However, as soon as I close the app, the data is lost. I am new to programming and assume this can be remedied by implementing the necessary functions in AppDelegate class, more specifically, under the default applicationWillTerminate function. If this is correct, how do I implement the data saving process? If not, where & how do I make sure data entered is stored so that fields are prepopulated the next time the app is opened?
If you need to store small amount of data, take a look at NSUserDefaults.
If your data better fits to a database, you can use SQLite (may be with a wrapper) or Core Data.
There is also a modern but not yet very mature cross-platform mobile database called Realm (partially open-sourced at the moment).
Since you are saving TextField data(which use mostly small string text) Use NSUserDefaults to store the string for persistence. What you need to do is at textFieldEndEditing save the text to NSUserDefaults and in viewDidLoad assign it to textField.
Saving To NSUserDefaults:
let defaults = NSUserDefaults.standardUserDefaults()
defaults.setObject(myTextField.text, forKey: "TextFieldText")
defaults.synchronize()
Retrieving from NSUserDefaults:
let defaults = NSUserDefaults.standardUserDefaults()
if let savedText = defaults.stringForKey("TextFieldText")
{
print("Textfield Text: \(savedText)")
}
I'm working on my first app and I need some help understanding what kind of data storage I need. I'm familiar with PHP, SQL, and databases but I don't know where to start with this project.
The app is pretty much a basic form with text fields, pickers, and uploaded images. At the end, the user will press submit and all of their data will be sent in an email.
What is the best way to store their data, so the user can go to previous screens and have their previously entered info still there. And then what is the best way to store the data after they press submit to send it in an email?,
Thanks so much for your help!
If it's just form data that you're storing once for submission, for simplicity sake, I recommend just stuffing it in a global dictionary that you can access from different views. Swift makes this easy by just adding an empty swift file and defining your dictionary at the top:
var myFormData: [String: AnyObject]()
You can now access "myFormData" form anywhere in your app, add and remove stuff from it.
You shouldn't technically need to "reload previous views" because of the way the navigation stack works. Anything you go back to should hold it's info.
If you really need to save the data to allow the user to close the app and then pick up where they left off much later, then I recommend simply kicking your dictionary to NSUserDefaults. It doesn't sound like something that needs to involve a database.
You can use a class called NSUserDefaults
var defaults: NSUserDefaults = NSUserDefaults.standardUserDefaults() //make an instance
defaults.setObject("Bob", forKey: "myName") //storing a value
defaults.synchronize() //synchronize data
println(defaults.objectForKey("myName")!) //retrieve the data