I want to save whichever indexpath I last clicked in the menu. He's recording indexpath right now. But if I choose indexpath, he's recording it. If I don't choose, it doesn't. How can I keep the previous record even if I don't select item from the menu?
let save11 = UserDefaults.standard.integer(forKey: "indexPath")
let yenindex = save11
self.menuView.setSelected(index: yenindex)
let userDefaults = UserDefaults.standard
userDefaults.removeObject(forKey: "indexPath")
menuView.didSelectItemAtIndexHandler = {(indexPath: Int) -> Void in
var placesdeger: String = ""
UserDefaults.standard.setValue(indexPath, forKey: "indexPath")
if indexPath == 0 {
let userDefaults = UserDefaults.standard
userDefaults.removeObject(forKey: "indexPath")
UserDefaults.standard.setValue(indexPath, forKey: "indexPath")
placesdeger = "Yatak Odası"
}
if indexPath == 1 {
let userDefaults = UserDefaults.standard
userDefaults.removeObject(forKey: "indexPath")
UserDefaults.standard.setValue(indexPath, forKey: "indexPath")
placesdeger = "Oturma Odası"
self.refreshData()
}
when ever you click on menu remove previous Userdefault value and set new user default value every time.
Put this code and get new index every time and if not selected then old value you will get in Userdefaults
let userDefaults = UserDefaults.standard
userDefaults.removeObject(forKey: "index")
userDefaults.set(i, forKey: "index")
EDIT1
USE THIS IN SOMEWHERE YOU DEFINE CONSTANT ONLY ONCE
let userDefaults = UserDefaults.standard
If you are using or any other method i dont know but if you get proper indexpath then this code will work
menuView.didSelectItemAtIndexHandler = {(indexPath: Int) -> Void in
var placesdeger: String = ""
userDefaults.removeObject(forKey: "indexPath")
if indexPath == 0 {
let userDefaults = UserDefaults.standard
UserDefaults.standard.setValue(indexPath, forKey: "indexPath")
placesdeger = "Yatak Odası"
}
if indexPath == 1 {
UserDefaults.standard.setValue(indexPath, forKey: "indexPath")
placesdeger = "Oturma Odası"
self.refreshData()
}
Related
I'm trying to store the value of the completion block into a dictionary. But I don't know how to access and store it in a local dictionary variable.
var id = String()
var answeredDict = [String:[String]]()
var answeredDictUsers = [String:String]()
override func viewDidLoad() {
super.viewDidLoad()
for user in answeredDict.keys{
let ref = Database.database().reference(fromURL: "URL").child("users/\(user)")
ref.child("name").observeSingleEvent(of: .value) { (snap) in
guard let name = snap.value as? String else { return }
self.answeredDictUsers.updateValue(name, forKey: user)
}
}
print(answeredDictUsers)
}
the print(answeredDictUsers) gives [:] (empty dictionary)
Data is loaded from Firebase asynchronously. By the time your print(answeredDictUsers) runs, the code inside the callback hasn't run yet. And since self.answeredDictUsers.updateValue(name, forKey: user) hasn't run yet, the print sees an empty array. You can easily test this for yourself by placing breakpoints on both those lines and running the code in the debugger.
This means that any code that needs data from the database, must be (called from) inside the callback/completion handler that gets that data from the database.
A very simple example:
for user in answeredDict.keys{
let ref = Database.database().reference(fromURL: "URL").child("users/\(user)")
ref.child("name").observeSingleEvent(of: .value) { (snap) in
guard let name = snap.value as? String else { return }
self.answeredDictUsers.updateValue(name, forKey: user)
print(answeredDictUsers)
}
}
The above will print the dictionary each time it has loaded one of your users' data.
If you only want to print the dictionary once the data for all users has been loaded, you could for example keep a counter:
let count = 0
for user in answeredDict.keys{
let ref = Database.database().reference(fromURL: "URL").child("users/\(user)")
ref.child("name").observeSingleEvent(of: .value) { (snap) in
guard let name = snap.value as? String else { return }
self.answeredDictUsers.updateValue(name, forKey: user)
count = count + 1
if count == dict.count {
print(answeredDictUsers)
}
}
}
I am trying to get the data I have saved and then load it into the TableView. Currently, if I am saving the object for the first time, the data gets encoded, saved, decoded, read and displayed correctly. However, if the key already exists and I am adding to the existing data, nothing gets displayed in the TableView.
This is currently how I am saving it in the first view controller:
let userEntry = UserEntries(date: String(todayDate), questions: [UserEntries.Question(question: q1Text, answer: q1Answer), UserEntries.Question(question: q2Text, answer: q2Answer)])
var allEntries : [UserEntries] = []
if doesKeyExist(key: "allEntries") == true {
let jsonDecoder = JSONDecoder()
if let data = UserDefaults.standard.data(forKey: "allEntries"),
let userEntries = try? jsonDecoder.decode(UserEntries.self, from: data) {
allEntries = [userEntries]
}
allEntries.insert(userEntry, at: 0)
let jsonEncoder = JSONEncoder()
if let value = try? jsonEncoder.encode(allEntries) {
UserDefaults.standard.set(value, forKey: "allEntries")
UserDefaults.standard.synchronize()
}
} else {
let jsonEncoder = JSONEncoder()
if let value = try? jsonEncoder.encode(userEntry) {
UserDefaults.standard.set(value, forKey: "allEntries")
UserDefaults.standard.synchronize()
}
}
let newViewController = storyboard?.instantiateViewController(withIdentifier: "tabViewController") as! UITabBarController
present(newViewController, animated: true, completion: nil)
}
This is how I'm displaying it in the TableView
var TableData : [UserEntries] = []
override func viewDidLoad() {
super.viewDidLoad()
let jsonDecoder = JSONDecoder()
if let data = UserDefaults.standard.data(forKey: "allEntries"),
let userEntries = try? jsonDecoder.decode(UserEntries.self, from: data) {
print(userEntries.date)
TableData = [userEntries]
}
// Uncomment the following line to preserve selection between presentations
// self.clearsSelectionOnViewWillAppear = false
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return TableData.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "entryCell", for: indexPath)
cell.textLabel?.text = TableData[indexPath.row].date
cell.detailTextLabel?.text = TableData[indexPath.row].questions[0].answer
return cell
}
I have a feeling that this is a logic error, in getting/displaying the data in the TableView, but am unsure of what exactly it is/how to fix it. Thank you for your help!
I don't know what your doesKeyExists function does but you can improve your data manipulation by this way:
let userEntry = UserEntries(date: String(todayDate), questions: [UserEntries.Question(question: q1Text, answer: q1Answer), UserEntries.Question(question: q2Text, answer: q2Answer)])
var allEntries : [UserEntries] = []
let jsonDecoder = JSONDecoder()
if let data = UserDefaults.standard.data(forKey: "allEntries"),
let userEntries = try? jsonDecoder.decode([UserEntries].self, from: data) {
allEntries = userEntries
}
allEntries.insert(userEntry, at: 0)
let jsonEncoder = JSONEncoder()
if let value = try? jsonEncoder.encode(allEntries) {
UserDefaults.standard.set(value, forKey: "allEntries")
UserDefaults.standard.synchronize()
}
let newViewController = storyboard?.instantiateViewController(withIdentifier: "tabViewController") as! UITabBarController
present(newViewController, animated: true, completion: nil)
}
And the problem with your controller is that you are saving only one entry to UserDefaults. Try to change your code to
let jsonDecoder = JSONDecoder()
if let data = UserDefaults.standard.data(forKey: "allEntries"),
let userEntries = try? jsonDecoder.decode([UserEntries].self, from: data) {
print(userEntries)
TableData = userEntries
}
I have a survey form that appear only if the user still didn't answer survey every time the user launch the app. But even if I already answered the survey still its appearing. Here's how I'm doing it
//Get if questionaire is done
let defaults = UserDefaults.standard
if let questionaire_done = defaults.string(forKey: "questionaire_done") {
print(questionaire_done) // Some String Value
}else {
performSegue(withIdentifier: "questionaireSegue", sender: nil)
}
UserDefaults.standard.set("yes", forKey: "questionnaire_done") //set the questionnaire as done
if let questionaire_done = defaults.string(forKey: "questionaire_done")
has a different key to
UserDefaults.standard.set("yes", forKey: "questionnaire_done")
Spell the keys the same, or better still, use a constant string for the key.
Store the value in before segue (navigation)
//Get if questionaire is done
let defaults = UserDefaults.standard
if let questionaire_done = defaults.string(forKey: "questionnaire_done") {
print(questionaire_done) // Some String Value
}else {
defaults.set("yes", forKey: "questionnaire_done") //set the questionnaire as done
performSegue(withIdentifier: "questionaireSegue", sender: nil)
}
If you want to validate your condition then you like
let defaults = UserDefaults.standard
if let questionaire_done = defaults.string(forKey: "questionnaire_done"), questionaire_done == "yes" {
print(questionaire_done) // Some String Value
}else {
defaults.set("yes", forKey: "questionnaire_done") //set the questionnaire as done
performSegue(withIdentifier: "questionaireSegue", sender: nil)
}
Yes, the key value name should be always same but one more thing - you should write this after any "UserDefaults" operation - either read or write.
UserDefaults.standard.synchronize()
Example -
UserDefaults.standard.set("yes", forKey: "questionnaire_done")
UserDefaults.standard.synchronize()
This is where the error is occuring, on the let selectedStudent line,
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
if(segue.identifier == "Student_segue") {
if let indexPath = self.tableView.indexPathForSelectedRow {
let selectedStudent = studentsSorted[indexPath.row]
let destination = segue.destinationViewController as! StudentInfoTableViewController
destination.selectedStudent = selectedStudent
}
}
}
Here is where I declare studentsSorted and studentArray.
typealias studentInfo = Dictionary<String, AnyObject>
typealias studentArray = [studentInfo]
let students = StudentRosterModel()
var studentsSorted:studentArray = studentArray()
var selectedRow:Int = 0
func updateStudentInfo(updatedStudent: Dictionary<String, AnyObject>) {
// replaced the selected row with the updated key/value dictionary
studentsSorted [selectedRow ] = updatedStudent
// sort the revised student list
studentsSorted.sortInPlace{ ($0["last_name"] as? String) < ($1["last_name"] as? String )}
// reload () tableView to show refreshed view
tableView.reloadData()
}
and this is where I declare selectedStudent,
class StudentInfoTableViewController: UITableViewController, UITextFieldDelegate {
var selectedStudent: Dictionary<String, AnyObject> = Dictionary<String, AnyObject>()
var delegate: studentUpdate?
Really confused here, I'd appreciate if someone could help me.
Thread 1:EXC_BAD_INSTRUCTION
This error almost print error into console log. I know this error can occurred by out of range error.
if let indexPath = self.tableView.indexPathForSelectedRow {
let selectedStudent = studentsSorted[indexPath.row]
let destination = segue.destinationViewController as! StudentInfoTableViewController
destination.selectedStudent = selectedStudent
}
If you declear self.tableView.indexPathForSelectedRow to indexPath and it succeed, then you consider indexPath.row is over or under at studentsSorted's size.
I am trying to save inputs from various text fields using NSUserDefaults:
#IBAction func continue2save(sender: AnyObject) {
let stringy1: NSString = mcweightTF.text!
let stringy2: NSString = mcnumTF.text!
NSUserDefaults.standardUserDefaults().setObject(stringy1, forKey: "savemcw")
NSUserDefaults.standardUserDefaults().setObject(stringy2, forKey: "savemcn")
NSUserDefaults.standardUserDefaults().synchronize()
}
#IBAction func calculate(sender: AnyObject) {
let load1: AnyObject? = NSUserDefaults.standardUserDefaults().objectForKey("savemcw")
calcLabel.text = String(load1)
}
However "load1"'s value is always nil. I have attempted almost every configuration of implementing short-term storage through NSUserDefaults, however the value stored is always nil.
Try this,
#IBAction func continue2save(sender: AnyObject) {
let stringy1 = mcweightTF.text!
let stringy2 = mcnumTF.text!
let defaults = NSUserDefaults.standardUserDefaults()
defaults.setObject("stringy1", forKey: "savemcw")
defaults.setObject("stringy2", forKey: "savemcn")
}
#IBAction func calculate(sender: AnyObject) {
let defaults = NSUserDefaults.standardUserDefaults()
let stringy1 = defaults.stringForKey("savemcw")
// Optional Chaining for stringy1
if let stringy = stringy1 {
calcLabel.text = stringy
}
}