1

I have a setting in my app that I am having issues retaining the state of. Basically, the UISwitch is on by default, however when updating my app to a newer version, it seems to switch off. I figured out that if the user has opened the settings menu in version 1.0, then this isn't an issue, however if they have never changed a setting, or even opened the settings menu, then it's a problem. Therefore, it must be an issue somewhere in viewWillAppear() but I can't figure out what it is. The code I have for storing the switches state seems really overcomplicated.

This is the code I have in my settings menu:

@IBAction func dupOffOnSwitch(sender: AnyObject) {
    if dupSwitch.on == true {
        autoAdjust = true
        println(autoAdjust)
    } else {
        autoAdjust = false
        println(autoAdjust)
    }

NSUserDefaults.standardUserDefaults().setBool(autoAdjust, forKey: "autoAdjustSettings")
}

override func viewWillAppear(animated: Bool) {

    autoAdjust = NSUserDefaults.standardUserDefaults().boolForKey("autoAdjustSettings")

    if autoAdjust == true {
        dupSwitch.on = true
    } else {
        dupSwitch.on = false
    }
}

    if userReturnedAuto == false {
        dupSwitch.on = true
        themeSwitch.on = false
        userReturnedAuto = true
        NSUserDefaults.standardUserDefaults().setBool(userReturnedAuto, forKey: "userReturnedAuto")
        NSUserDefaults.standardUserDefaults().setBool(userReturnedAuto, forKey: "autoAdjustSettings")
    }

I am declaring the bool 'autoAdjust' in a different view controller as a global variable. In that same view controller in viewWillAppear() I have this code:

    autoAdjust = NSUserDefaults.standardUserDefaults().boolForKey("autoAdjustSettings")

Can anyone suggest a better way of storing the switches state while also having it on by default when the app is first launched? Or a fix to my current solution.

user3746428
  • 11,047
  • 20
  • 81
  • 137
  • Try `NSUserDefaults.standardUserDefaults().synchronize()` after you store any value in `NSUserDefaults`. – Kirsteins Nov 04 '14 at 11:25

2 Answers2

1

Not sure if this is over kill(or just stupid). But why not use CoreData to save all the users settings. Then when the app becomes active(in your appDelegate) you can set the NSUserDefaults from these stored values. Just a thought :)

For shortness I will only make an example for one switch, you can then fill out and add the rest. I will also assume you will be updating the NSUserDefaults when the switch changes state. We will only update/save the core data when the app goes to in-active and load settings once when app becomes active.

Also if anyone sees something I missed or could be done better please let me know and I will update the answer.

First off you need to make sure you import the CodeData libraries into your view controller:

import CoreData

class fooBarViewController: UIViewController {

You need to create and entity in core data: lets assume it is called "Settings" then once you have created the entity, you need to add some attributes. Press the "+" symbol. Now add the attribute and set the name to "dupSwitch" and type to "Boolean". Add an attribute for each setting you need to store.

Next: You need to create a new swift file. Type NSObject. name it something like "dataObjects". Inside you you will use the following code: (first remove all current code - make it blank)

import UIKit
import CoreData

@objc(settingObj) 
class settingObj: NSManagedObject {

@NSManaged var dupSwitch:NSNumber //do this for each setting
}

Next you need to go back to your CoreData dataModel and do the following.

1. click on "Default" under the section "Configuration"
2. You will then get a list of all your "entities" select "Settings"
3. click on class and edit the field to "settingObj"

Now that you have you CoreData set up. You can now save/edit/delete data as need be. For example when you need to load all saved user settings when app goes will become active.

in your AppDelegate.swift file: import the CoreData libraries.

 import CoreData

then add this function if it is not already present

func applicationWillEnterForeground(application: UIApplication) {

}

inside "applicationWillEnterForeground" you will load any settings that have been stored in CoreData

    var results:[settingObj] = []

    let appDel:AppDelegate = UIApplication.sharedApplication().delegate as AppDelegate
    let context:NSManagedObjectContext = appDel.managedObjectContext!
    let req = NSFetchRequest(entityName: "Settings")

    let tapResults = context.executeFetchRequest(req, error: nil)

    if let presentResults = tapResults {
        if let castedResults = presentResults as? [settingObj] {
            for item in castedResults {

                let dupSwitch = item.dupSwitch    
                let settingSwitch = item.whateverElseYouNeedExample 

           //now based on this we can set the NSDefault
           NSUserDefaults.standardUserDefaults().setBool(dupSwitch, forKey: "autoAdjustSettings")
           NSUserDefaults.standardUserDefaults().setBool(settingSwitch, forKey: "whateverElseYouNeedExample")
            }
        }
    }

Now when you want to save the users settings. I would would just it when app goes in-active. First we will check if the settings have already been saved. If so, then we will just perform an update. If not, we will save a new entry into yuor CoreData Entity.

add the following func to your appDelegate(if not already there):

func applicationDidEnterBackground(application: UIApplication) {

}

EDIT I HAVE TO GO TO WORK WILL COMPLETE REST OF ANWSER WHEN I GET BACK HOME. REALLY SORRY.

the_pantless_coder
  • 2,297
  • 1
  • 17
  • 30
  • I would give this a try, but I have no experience with CoreData at the moment and I need a quick fix for now. Thanks anyway! – user3746428 Nov 06 '14 at 21:52
  • 1
    @user3746428 I get back home later tomorrow and will post a complete answer when I am at comp with xcode on it. try this tutorial in the meantime http://www.youtube.com/watch?v=3IDfgATVqHw – the_pantless_coder Nov 07 '14 at 00:09
1

NSUserDefaults.standardUserDefaults().boolForKey("key") defaults to false. Therefore, as in your case, if the user never sets the key, then it will be false and the switch will default to off.

Instead, rename the key and use it as the negative. So instead, call it autoAdjustSettingsOff which will default to false and the switch will default to on. Don't forget to switch around the true/false settings in your conditional blocks.

Ron Fessler
  • 2,701
  • 1
  • 17
  • 22