How do I save a var when my iOS app closes? [duplicate] - ios

This question already has answers here:
How to save local data in a Swift app?
(12 answers)
Closed 6 years ago.
In total I have 2 viewcontrolers. The App is the same like this guy made in a tutorial. https://www.youtube.com/watch?v=LrCqXmHenJY&t=40s
To make a start, I made a var:
import UIKit
var list = ["Task 1", "Task 2", "Task 3", "Task 4"]
class FirstViewController: UIViewController , UITableViewDelegate, UITableViewDataSource{
My current problem is, that when I close the app no ToDo's which I created were saved.
What do I need to do to save my var list so that my ToDo-List isn't empty when I open it for the next time?

You can use UserDefaults to save/load application state or configurations. For complex requirements use CoreData
Writing/Saving before app termination
let defaults = UserDefaults.standard
defaults.set(true, forKey: "Enabled")
Reading/Loading on app launch
let defaults = UserDefaults.standard
let enabled = defaults.bool(forKey: "Enabled")
Read the related Apple docs here.

If you want an easy way to store a list of strings, you can use UserDefaults. Another way to do this is to use Core Data which is more difficult to use. It is usually used to store more complex data structures than an array of strings.
To save the string array to UserDefaults, do this:
UserDefaults.standard.set(list, "myStringArray")
You can replace "myStringArray" with any key you want.
To retrieve it, do this:
list = UserDefaults.standard.stringArray(forKey: "myStringArray")
I suggest you save the array in this method in App Delegate:
func applicationDidEnterBackground(_ application: UIApplication) {
}
For more info on User Defaults, see https://developer.apple.com/reference/foundation/userdefaults

You have very simple needs. Look at NSUserDefaults (now called UserDefaults in Swift 3.)
Save your data to UserDefaults when it changes, and read it back when you display your view controller.
As Eric says in his comments, make list an instance variable of your view controller.
EDIT:
In the comments below, rmaddy pointed out that the app will be saving a to-do list. That will likely grow in complexity from an array of a handful of items to a larger array or potentially a more complex structure.
Given that, you might want to look at saving your data to a plist file in the documents directory (quite simple) or using NSCoding if you have custom objects other than the small list of "property list" types that can be saved to a plist.
Both of those solutions read and write the data all at once to a file. That might be ok for a to-do list app.
If you need to change parts of a larger data-set and leave the rest unchanged then it's time to consider a database like Core Data.

Related

Should I use NSUserDefault, dictionaries, core data - or something else?

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.

Swift How to fix errors with Target Membership?

I am beginner to Swift and I am not aware of all the little details, so please forgive if it's a stupid question
My app is in quite advanced stage of development, so I would like to not mess with the existing code as little as possible. My problem is that I want to implement Today Extension in my app, in it I want to display a tableView that will display data from a single array from my "Plum" class and I need one method from the class to handle the selection. Unfortunately when I change the Plum's target membership to TodayExtension a whole bunch of errors are shown because many APIs from that class aren't available to TodayExtension. The class inherits from AVAudioPlayer so most essential methods aren't available in Extension.
I tried to create a helper class that would get the array from Plum and return it in method to my TableView but that still doesn't work because of "Use of unresolved identifier 'Plum'"
How can I obtain the array and use the method?
I think while adding Today Extension you might have got some classes for today extension,
You can use App Group with User Defaults functionality to transfer data from iOS app to today Extension classes
1) To set data you can use
var defaults: NSUserDefaults = NSUserDefaults(suiteName: <GroupID>)!
defaults.setObject(<YourArray, forKey:<KeyName>)
2) In Today Extension target's Class you can fetch that array like this
var defaults: NSUserDefaults = NSUserDefaults(suiteName: <GroupID>)!
var <YourArray> = defaults.stringForKey(<KeyName>)
Note : This is just pseudo code might contain error
Adding the Plum class in the today extension is a bad idea. Extensions should be lightweight and you only need to transfer the data needed.
In your case you may need the array of title and description. So form a array of dictionary with needed details and store these details in App group user defaults like #Hitesh answer.
In your today extension class, read this array from the user defaults then display the details in the table view.

How to store an updated set of questions and answers in iOS/Swift and persist it

I'm starting a relatively simple app which presents a series of multiple choice questions. There will be 4 possible answers (A/B/C/D) and more than one choice can be correct. While manipulating such an object (one instance of a question with its accompanying answers) I've created the following data structure:
public class QAData {
var questionText: String
var answers: [String] // Will contain 4 separate answer options
var correct: [Bool] // contains 4 boolean values to match against options of answers to record correct answer/s
var selected: [Bool] // Will be updated to true if user selects relevant answer option
}
My question is what is the best way to store all the questions and answers in my app which also allows me to update the 'selected' attribute and store it across app launches? I'll initially have 100 questions however this could increase over time up to 1000.
Options I've considered is having an array containing all the data which is saved to user defaults - perhaps not really what it's designed for?
Persisting the object using NSCoding?
Or having the data in a SQLite database?
Any recommendations?
I guess saving of large amount of data in UserDefault is not a good way. It will badly affect to your application performance later on as your number of question might be increase.
I think coredata framework suit to your requirement . You can manage one entity in coredata which will persist all your questions with its four options, its boolean answers and user's selected answers. And you can easily save,update and retrieve data from local database using coredata.
You can save data in .Plist File or CoreData/Sqlite database. If all Q/A are static then prefer .plist file is better way.
If the Q&A are more less static and get only updated by you, store them in an asset (e.g in an HTML file) and read this file to access them.

How to save entered data to make it available after app restart

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)")
}

How to store form data in a swift app

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

Resources