import UIkit
// ViewController file
class ViewController: UITableViewController, UIViewController{
#IBAction func aaaSwitch(_ sender: UISwitch) {
if (sender.isOn == true)
{
ClickCounterA+=2
UserDefaults.standard.set(aaaSwitch, forKey: "aaaSwitch")
UserDefaults.standard.bool(forKey: "aaaSwitch")
defaults.set(aaaSwitch, forKey: "aaaSwitch")
}
else
{
defaults.set(aaaSwitch, forKey: "aaaSwitch")
}
}
I change the switch(aaaSwitch) in tableview and move to another tableview. After that, I return to the first tableview, the switch is the statement before I change. In other words, I can't save the switch statement.
The problem is you're passing aaaSwitch, the method, into the UserDefaults set calls. You want to be passing in a value, in this case a boolean value.
UserDefaults.standard.set(sender.isOn, forKey: "aaaSwitch")
If you really wanted to archive your entire UISwitch, you'd need to first convert it to an NSData (and you'd likely have to come up with an algorithm for doing so). And I can see no point in ever wanting to do that. Surely you just want to persist its on/off state, so use the above code.
class ViewController: UITableViewController, UIViewController{
#IBOutlet weak var aaaswitch: UISwitch!
override func viewWillAppear(_ animated: Bool) {
aaaswitch.isOn = UserDefaults.standard.bool(forKey: "aaaSwitch")
}
#IBAction func aaaSwitch(_ sender: UISwitch) {
if (sender.isOn == true)
{
....
}
else
{
....
}
UserDefaults.standard.set(sender.isOn, forKey: "aaaSwitch")
}
}
Related
I would like to save the state of a UISwitch label with UserDefaults. My code looks like this:
func viewDidAppear() {
mySwitch.setOn(userDefaults.standard.bool(forKey: "mySwitchValue"), animated: true)
}
func viewWillDesappear() {
UserDefaults.standard.set(mySwitch.isOn, forKey: "mySwitchValue")
}
But in the app, when I leave the switch view, and I return in, the UISwitch isn't as I turned it.
Probably, what rmaddy pointed out earlier is the issue. In that case go for spell thingy.
Otherwise, it is possible that setting the value of your switch's state when view is disappearing is not a judicious choice. As when application goes into background other processes are acted upon alongside, and probably setting default is not effected before application closes.
I would generally set such values when I am calling such functions, i.e., in the switch action. As soon as a user changes the switch state, save it in defaults, that way when you retrieve it when viewDidAppear, it will work.
import UIKit
class ViewController: UIViewController {
let userDefaults = UserDefaults.standard
#IBOutlet weak var mySwitch: UISwitch!
#IBAction func switchAction(_ sender: UISwitch) {
userDefaults.set(sender.isOn, forKey: "mySwitchValue")
}
override func viewDidAppear(_ animated: Bool) {
mySwitch.isOn = userDefaults.bool(forKey: "mySwitchValue")
}
}
Demo below:
This is not an answer to your original query, but an answer to another query in the comment. Question: How to set the default state of UISwitch as on, if application is launched for the first time?
Though ideally, it should be asked as another question, given it is incremental, the code is below:
import UIKit
class ViewController: UIViewController {
let userDefaults = UserDefaults.standard
var firstTimeAppLaunch: Bool {
get {
// Will return false when the key is not set.
return userDefaults.bool(forKey: "firstTimeAppLaunch")
}
set {}
}
#IBOutlet weak var mySwitch: UISwitch!
#IBAction func switchAction(_ sender: UISwitch) {
userDefaults.set(sender.isOn, forKey: "mySwitchValue")
}
override func viewDidLoad() {
super.viewDidLoad()
if !firstTimeAppLaunch {
// This will only be trigger first time the application is launched.
userDefaults.set(true, forKey: "firstTimeAppLaunch")
userDefaults.set(true, forKey: "mySwitchValue")
}
// Do any additional setup after loading the view, typically from a nib.
}
override func viewDidAppear(_ animated: Bool) {
mySwitch.isOn = userDefaults.bool(forKey: "mySwitchValue")
}
}
Note that you could do this within AppDelegate's function:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Could add the above code within this as well. Upto you.
return true
}
I'm trying to save a bool value to UserDefaults from a UISwitch, and retrieve it in another view. However, I've tried following multiple tutorials and stack answers and none seem to work.
This is how I'm saving it:
class SettingsViewController: UITableViewController {
#IBOutlet weak var soundSwitchOutlet: UISwitch!
#IBAction func soundSwitch(_ sender: UISwitch) {
UserDefaults.standard.set(soundSwitchOutlet.isOn, forKey: "sound")
}
and this is how I'm trying to retrieve it in another view:
if let savedValue = UserDefaults.standard.bool(forKey: "sound") {
boolValue = savedValue
}
//this is inside viewDidLoad and "boolValue" was declared outside viewDidLoad//
For a reason this code is giving me errors and none of the things I've tried have worked. How can I save a bool to UserDefaults and retrieve it in another view?
Edit: I think I fixed the first part. However, the way I'm retrieving the boolean seems to be totally wrong. Also: No other stackExchange answer responds to what I'm asking, at least not in swift.
As Leo mentioned in the comments bool(forKey returns a non-optional Bool. If the key does not exist false is returned.
So it's simply
boolValue = UserDefaults.standard.bool(forKey: "sound")
Calling synchronize() as suggested in other answers is not needed. The framework updates the user defaults database periodically.
Do it like this.
In your first view controller.
create an IBoutlet connection to your UISwitch
And then the action for your UISwitch. so in the end, your first view controller should look like this.
import UIKit
class FirstViewController: UIViewController {
#IBOutlet weak var myswitch: UISwitch! // Outlet connection to your UISwitch (just control+ drag it to your controller)
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
#IBAction func myswitchAction(_ sender: Any) { // Action for your UISwitch
var myswitctBool : Bool = false // create a local variable that holds your bool value. assume that in the beginning your switch is offed and the boolean value is `false`
if myswitch.isOn == true { // when user turn it on then set the value to `true`
myswitctBool = true
}
else { // else set the value to false
myswitctBool = false
}
// finally set the value to user default like this
UserDefaults.standard.set(myswitctBool, forKey: "mySwitch")
//UserDefaults.standard.synchronize() - this is not necessary with iOS 8 and later.
}
}
End of the first view controller
Now in your second view controller
you can get the value of userdefault, which you set in first view controller. I put it in the viewdidload method to show you how it works.
import UIKit
class SecondViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let myswitchBoolValuefromFirstVc : Bool = UserDefaults.standard.bool(forKey: "mySwitch")// this is how you retrieve the bool value
// to see the value, just print those with conditions. you can use those for your things.
if myswitchBoolValuefromFirstVc == true {
print("true")
}
else {
print("false")
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
Hope this will help to you. good luck
Use this line of code:
#IBAction func soundSwitch(_ sender: UISwitch) {
UserDefaults.standard.set(soundSwitchOutlet.isOn, forKey: "sound")
}
insteadof :
#IBAction func soundSwitch(_ sender: UISwitch) {
UserDefaults.standard.set(soundSwitchOutlet, forKey: "sound")
}
Try this:
#IBAction func soundSwitchs(_ sender: Any)
{
UserDefaults.standard.set(soundSwitchOutlet.isOn, forKey: "sound")
UserDefaults.standard.synchronize()
}
//this is inside viewDidLoad and "boolValue" was declared outside viewDidLoad//
boolValue = UserDefaults.standard.bool(forKey: "sound")
Ok so I am trying to make it when the user flips the cheat mode switch it will disable the answerButton. I did try to set the button to disable near the bottom however it does not appear to do anything. I added the print("") to see if it would print in the console however nothing was printed. I a unsure what is wrong here.
I have pasted my code below.
import Foundation
import UIKit
class SettingsController: UITableViewController {
#IBOutlet weak var cheatSwitch: UISwitch!
override func viewDidLoad() {
super.viewDidLoad()
cheatSwitch.isOn = UserDefaults.standard.bool(forKey: "switchState")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func saveSettings(_ sender: UISwitch) {
UserDefaults.standard.set(cheatSwitch.isOn, forKey: "switchState")
UserDefaults.standard.synchronize()
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let mainView : ViewController = segue.destination as! ViewController
if cheatSwitch.isOn == true {
print("turn off button")
mainView.btnAnswer.isEnabled = false;
}
else {
print("turn on button")
mainView.btnAnswer.isEnabled = true;
}
}
}
You are saving the value UISwitch's state in UserDefaults so you can use its value in ViewController's method viewDidApper.
override func viewDidAppear(_ animated: Bool) {
self.btnAnswer.isEnabled = !UserDefaults.standard.bool(forKey: "switchState")
}
Note: There is no need to add prepareForSegue in your SettingsController because it will never called when you press back button of NavigationController so consider to remove it.
I am working on a settings view for a basic app. Basic, in there is just one switch in the settings view for the user. The switch setting is saved with NSUserDefault. I use a delegate to send the switch signal from the settings view to the main view. The delegation works properly.
The UI is basic. On the main view, a label will read On in green (if the switch is on) and Off in red (if the switch is off.) There is a setting button in the top right that will segue (settingsSegue) to the settings UITableViewController, where the UISwitch is located.
The problem is loading up the NSUserDefault once the app loads. In viewDidLoad, I check to see if there's a value saved for the switch key. If there is, load it up. If not, set it to false (in the storyboard, the switch is set to false as default.) The Switch Status loads up as Off every time. Even if the default value is On. This shouldn't be happening.
ViewController.swift:
import UIKit
var nsDefaults = NSUserDefaults.standardUserDefaults()
class ViewController: UIViewController, SettingsViewControllerDelegate {
var onFromMain = Bool()
#IBOutlet weak var switchStateLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
if let mySavedKey = nsDefaults.objectForKey("savedSwitchSettingDefault") {
// A value exists. Load it up.
nsDefaults.objectForKey("savedSwitchSettingDefault")
print("The switch is set! \(mySavedKey)")
checkSwitchState()
}
else {
// Nothing stored in NSUserDefaults yet. Set switch to False.
nsDefaults.setBool(false, forKey: "savedSwitchSettingDefault")
checkSwitchState()
}
}
func myVCDidFinish(controller: SettingsViewController, switchState: Bool) {
onFromMain = switchState.boolValue
checkSwitchState()
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "settingsSegue" {
let nav = segue.destinationViewController as! UINavigationController
let secondVC = nav.topViewController as! SettingsViewController
secondVC.delegate = self
}
}
func checkSwitchState() {
if onFromMain {
switchStateLabel.text = "On"
switchStateLabel.textColor = UIColor.greenColor()
}
else {
switchStateLabel.text = "Off"
switchStateLabel.textColor = UIColor.redColor()
}
}
}
SettingsViewController.swift:
import UIKit
protocol SettingsViewControllerDelegate {
func myVCDidFinish(controller: SettingsViewController, switchState: Bool)
}
class SettingsViewController: UITableViewController {
var delegate: SettingsViewControllerDelegate? = nil
#IBOutlet weak var switchOutlet: UISwitch!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
switchOutlet.on = nsDefaults.boolForKey("savedSwitchSettingDefault")
}
#IBAction func closeSettingsPageBarButtonItemPressed(sender: UIBarButtonItem) {
if (delegate != nil) {
delegate!.myVCDidFinish(self, switchState: switchOutlet.on)
self.dismissViewControllerAnimated(true, completion: nil)
}
}
#IBAction func switchPressed(sender: UISwitch) {
// Tap the switch to change the setting.
nsDefaults.setBool(switchOutlet.on, forKey: "savedSwitchSettingDefault")
}
}
I believe my problem lies somewhere in loading up the default key for "savedSwitchSettingDefault". Is this correct? Or does the issue lie elsewhere in the code?
You can tidy things up quite a bit by relying on the fact that the default you want is false and that boolForKey gives you false when the key isn't present.
Also, by accessing the setting in viewWillAppear you can avoid the need for the delegate callback.
ViewController.swift
import UIKit
class ViewController: UIViewController {
let nsDefaults = NSUserDefaults.standardUserDefaults()
var onFromMain = false
#IBOutlet weak var switchStateLabel: UILabel!
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
self.onFromMain = self.nsDefaults.boolForKey("savedSwitchSettingDefault")
self.checkSwitchState()
}
func checkSwitchState() {
if self.onFromMain {
switchStateLabel.text = "On"
switchStateLabel.textColor = UIColor.greenColor()
}
else {
switchStateLabel.text = "Off"
switchStateLabel.textColor = UIColor.redColor()
}
}
}
SettingsViewController.swift:
import UIKit
class SettingsViewController: UITableViewController {
let nsDefaults = NSUserDefaults.standardUserDefaults()
#IBOutlet weak var switchOutlet: UISwitch!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
self.switchOutlet.on = self.nsDefaults.boolForKey("savedSwitchSettingDefault")
}
#IBAction func closeSettingsPageBarButtonItemPressed(sender: UIBarButtonItem) {
self.dismissViewControllerAnimated(true, completion: nil)
}
#IBAction func switchPressed(sender: UISwitch) {
// Tap the switch to change the setting.
self.nsDefaults.setBool(self.switchOutlet.on, forKey: "savedSwitchSettingDefault")
}
}
When retrieving the bool value from User Defaults, boolForKey will return false if the value doesn't exist. So in this case there's no need for unwrapping. From the documentation:
If a boolean value is associated with defaultName in the user defaults, that value is returned. Otherwise, false is returned.
If the value is getting set (you are sure of it), and the behavior of the app is not working correctly your problem might lie elsewhere.
I would recommend using another approach, declare your "onFromMain" as an optional boolean, then unwrap it when you need it.
var onFromMain: Bool?
...
func checkSwitchState() {
//- This will unwrap your optional or set false if its nil
let switchSate = onFromMain ?? false
//- Then you can set the values based on the value (or the default false)
switchStateLabel.text = switchState ? "On" : "Off"
switchStateLabel.textColor = switchState ? UIColor.greenColor() : UIColor.redColor()
}
Then attach the debugger with a breakpoint and see if the value is being unwrapped or if its defaulting to false.
Also, you are setting your delegate only when the segue is called, depends of the scenario, and if i understand you correctly, you migt not get the value until you have actually navigated to the settings view. So when opening the app (without navigating to the settings view) the onFromMain will never get populated.
Alternatively you can fetch the value on the view did load method to get it straight away when you load the app.
When I move from one view controller to another, the switch on the first controller resets itself and does not retain its state.
How can I make it save its state when come back to it after viewing other controllers? And how do I make it save its state after closing the app. I have looked at the various stackOverflow questions and responses and the apple documentation, but nothing seems to work.
Here is my class for the View Controller that has the switch.
class Days: UIViewController {
#IBOutlet weak var switchButton: UISwitch!
var switchState = true
let switchKey = "switchState"
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
#IBAction func saveSwitchPressed(sender:AnyObject) {
if self.switchButton.on {
self.switchState = true
NSUserDefaults.standardUserDefaults().setBool(self.switchState, forKey: switchKey)
NSUserDefaults.standardUserDefaults().synchronize()
println(NSUserDefaults.standardUserDefaults().boolForKey(switchKey))
} else {
self.switchState = false
NSUserDefaults.standardUserDefaults().setBool(self.switchState, forKey: switchKey)
NSUserDefaults.standardUserDefaults().synchronize()
println(NSUserDefaults.standardUserDefaults().boolForKey(switchKey))
}
}
}
I'm a beginner to Swift and generally Xcode. Thank you in advance for your time and help :)
Xcode 8.3 • Swift 3.1
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var switchButton: UISwitch!
override func viewDidLoad() {
super.viewDidLoad()
switchButton.isOn = UserDefaults.standard.bool(forKey: "switchState")
}
#IBAction func saveSwitchPressed(_ sender: UISwitch) {
UserDefaults.standard.set(sender.isOn, forKey: "switchState")
}
}
Since you're syncing the on/off state of the switch you could on viewWillAppear: or viewDidAppear: set the state of the switch to the value stored in NSUserDefaults
Something along the lines of
override func viewWillAppear(animated: Bool) {
self.switchButton.on = NSUserDefaults.standardUserDefaults().boolForKey(switchKey)
}
just after code connect UISwitch to IBoutlet.
class ViewController: UIViewController {
#IBOutlet weak var switchButton: UISwitch!
#objc func switchStateDidChange(_ sender:UISwitch!)
{
if (sender?.isOn == true){
print("on")
}
else {
print("off")
}
UserDefaults.standard.set(sender.isOn, forKey: "switchState")
UserDefaults.standard.synchronize()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(false)
switchButton?.isOn = UserDefaults.standard.bool(forKey: "switchState")
switchButton?.addTarget(self, action: #selector(switchStateDidChange(_:)), for: .touchUpInside)
}
}