JohnJLilley
JohnJLilley

Reputation: 173

Saving state of UIButton (checkbox) - Swift

I'm a new developer and I'm making a to-do list app in Swift. I was able to figure out how to change the state of the UIButton (checkbox) on clicking. At the moment I'm trying to figure out how to save that state for when I exit the app or switch views and return. I was able to successfully save the text (to-do list tasks) by using NSUserDefaults and have also experimented with it on my buttons but cannot figure out how to get it to work.

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

var myButton: Qbutton!

override func viewDidLoad() {
    super.viewDidLoad()

    var isChecked = NSUserDefaults.standardUserDefaults().boolForKey("isBtnChecked") // here we obtain the last state of the button
    myButton.isChecked = isChecked
    self.view.addSubview(myButton)

I have the UIButton in a subclass of QButton.

class Qbutton: UIButton {

    var isSelected: Bool = defaults.boolForKey("isButtonChecked")

    // Images
    let selectedImage = UIImage(named: "Selected")
    let unselectedImage = UIImage(named: "Unselected")


    //Bool Property
    var isChecked:Bool = false{
        didSet{
            if isChecked == true{
                self.setImage(selectedImage, forState: UIControlState.Normal)
            }else{
                self.setImage(unselectedImage, forState: UIControlState.Normal)
            }
            defaults.setObject(isChecked, forKey: "isButtonChecked")
        }
    }

    override init(frame: CGRect){
    super.init(frame:frame)
    self.layer.masksToBounds = true
    self.setImage(unselectedImage, forState: UIControlState.Normal)

    self.addTarget(self, action: "buttonClicked:", forControlEvents: UIControlEvents.TouchUpInside)
    self.isChecked = false
}

required init(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
}

func buttonClicked(sender: UIButton) {
    if(sender == self){
        if isChecked == true{
            isChecked = false
        }else{
            isChecked = true
        }
    }
}
}

Upvotes: 0

Views: 6493

Answers (2)

Scott
Scott

Reputation: 1222

I think you are completely over-thinking it and making it complicated. Since it's just a simple button the easiest way to do it is set a bool through an IBAction. Let me know if I'm missing something from your question though.

In Objective-C it would be something like this..

{
    BOOL _isStateEnabled;
}

-(IBAction)clickedButton: (id)sender {
    _isStateEnabled = !_isStateEnabled;
}

In Swift I'm not fluent but, something like this..

{
    let _isStateEnabled as boolean;
}

func buttonClicked(sender: UIButton) {
    _isStateEnabled = !_isStateEnabled;
}

Upvotes: 0

mauricioconde
mauricioconde

Reputation: 5132

well i think you can save the state of the UIButton with the NSUserDefaults just when the variable isChecked is changed. Something like this:

var isChecked:Bool = false{
    didSet{
        if isChecked {
            self.setImage(selectedImage, forState: UIControlState.Normal)
        }else{
            self.setImage(unselectedImage, forState: UIControlState.Normal)
        }
        NSUserDefaults.standardUserDefaults().setObject(isChecked, forKey: "isBtnChecked")
        // this method is automatically invoked at periodic intervals, but
        //if you cannot wait for the automatic synchronization you can invoke it
        NSUserDefaults.standardUserDefaults().synchronize() 
    }


}

Now when your app is launched you can check the last state of the UIButton with this:

var isSelected: Bool = NSUserDefaults.standardUserDefaults().boolForKey("isBtnChecked")

UPDATE

I made an example using your Qbutton class. I hope this can help you:

import Foundation
import UIKit

class Qbutton: UIButton {

    // Images
    let selectedImage = UIImage(named: "Selected")
    let unselectedImage = UIImage(named: "Unselected")

    //Bool Property
    var isChecked:Bool = false{
        didSet{
            if isChecked {
                self.setImage(selectedImage, forState: UIControlState.Normal)
            }else{
                self.setImage(unselectedImage, forState: UIControlState.Normal)
            }
            NSUserDefaults.standardUserDefaults().setObject(isChecked, forKey: "isBtnChecked")
            // this method is automatically invoked at periodic intervals, but
            //if you cannot wait for the automatic synchronization you can invoke it
            NSUserDefaults.standardUserDefaults().synchronize()
        }
    }

    override init(frame: CGRect){
        super.init(frame:frame)
        self.layer.masksToBounds = true
        self.setImage(unselectedImage, forState: UIControlState.Normal)

        self.addTarget(self, action: "buttonClicked:", forControlEvents: UIControlEvents.TouchUpInside)
        self.isChecked = false
    }

    required init(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }

    func buttonClicked(sender: UIButton) {
        if(sender == self){
            if isChecked == true{
                isChecked = false
                self.setImage(unselectedImage, forState: UIControlState.Normal)
            }else{
                isChecked = true
                self.setImage(selectedImage, forState: UIControlState.Normal)
            }
        }
    }
}

Now in the UIViewController i create a Qbutton and before i add it to the UIViewController view i read the last state of the variable "isBtnChecked".

From the official docs:

If a boolean value is associated with defaultName in the user defaults, that value is returned. Otherwise, NO is returned.

import UIKit
class ViewController: UIViewController {
    var myButton: Qbutton!

    override func viewDidLoad() {
        super.viewDidLoad()

        myButton = Qbutton(frame: CGRectMake(100,100,50 ,50));
        var isChecked = NSUserDefaults.standardUserDefaults().boolForKey("isBtnChecked") // here we obtain the last state of the button
        myButton.isChecked = isChecked // we set the value
        self.view.addSubview(myButton)

    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()

    }
}

UPDATE 2

Here is an example using the selected property of UIButton

import Foundation
import UIKit

class Qbutton: UIButton {

    // Images
    let selectedImage = UIImage(named: "Selected")
    let unselectedImage = UIImage(named: "Unselected")


    //Bool Property
    override var selected: Bool{
        didSet{
            if selected {
                self.setImage(selectedImage, forState: UIControlState.Normal)
            }else{
                self.setImage(unselectedImage, forState: UIControlState.Normal)
            }
            NSUserDefaults.standardUserDefaults().setObject(selected, forKey: "isBtnChecked")
            NSUserDefaults.standardUserDefaults().synchronize()
        }
    }

    override init(frame: CGRect){
        super.init(frame:frame)
        self.layer.masksToBounds = true
        self.setImage(unselectedImage, forState: UIControlState.Normal)

        self.addTarget(self, action: "buttonClicked:", forControlEvents: UIControlEvents.TouchUpInside)
    }

    required init(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
   }

    func buttonClicked(sender: UIButton) {
        self.selected = !self.selected
    }
}

And the UIViewController :

import UIKit
class ViewController: UIViewController {
    var myButton: Qbutton!

    override func viewDidLoad() {
        super.viewDidLoad()

        myButton = Qbutton(frame: CGRectMake(100,100,50 ,50));
        myButton.selected = NSUserDefaults.standardUserDefaults().boolForKey("isBtnChecked") // here we obtain the last state of the button
        self.view.addSubview(myButton)

    }
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()

    }
}

I hope this really can help you!

Upvotes: 1

Related Questions