How do I save a buttons image state in Swift? - swift

I have this like button and when the user pressed on it the image changed to another image. How would I be able to save the new image when I close my app and open it up again. I have the code below and Im using NSUserDefaults but its not saving the changed image. Here is the code:
override func viewDidLoad() {
super.viewDidLoad()
UserDefaults.standard.set(true, forKey: "Change")
}
#IBAction func addToLikes(_ sender: Any) {
//progressView.isHidden = false
if UserDefaults.standard.bool(forKey: "Change") {
likedButton.setImage(UIImage(named: "selected_star"), for: .normal)
}
}

Got it to work:
override func viewDidLoad() {
super.viewDidLoad()
if UserDefaults.standard.bool(forKey: "starSelected") {
likedButton.setImage(UIImage(named: "selected_star"), for: .normal)
print("star selected")
}
if UserDefaults.standard.bool(forKey: "starNotSelected") {
likedButton.setImage(UIImage(named: "not_selected_star"), for: .normal)
print("star not selected")
}
}
}
#IBAction func addToLikes(_ sender: Any) {
//progressView.isHidden = false
likedButton.isSelected = !likedButton.isSelected
if likedButton.isSelected {
print("I am selected.")
likedButton.setImage(UIImage(named: "selected_star"), for: .normal)
UserDefaults.standard.set(false, forKey: "starNotSelected")
UserDefaults.standard.set(true, forKey: "starSelected")
} else {
likedButton.setImage(UIImage(named: "not_selected_star"), for: .normal)
UserDefaults.standard.set(false, forKey: "starSelected")
UserDefaults.standard.set(true, forKey: "starNotSelected")
print("I am not selected.")
}

Related

swift. UserDefaults and UISwitch

I'm trying to get UserDefaults to work with a UISwitch, but the switch state is not saving when I force close the app and reopen it.
Update: Got it to work. The switch state will stay in either the "on" or "off" state even when the app is closed.
My code:
let defaults = UserDefaults.standard
#IBAction func switchAction(_ sender: UISwitch) {
defaults.set(true, forKey: "saveTrue")
defaults.set(false, forKey: "saveFalse")
if sender.isOn == false {
sender.setOn(defaults.bool(forKey: "saveFalse"), animated: true)
} else if sender.isOn == true {
sender.setOn(defaults.bool(forKey: "saveTrue"), animated: true)
}
}
ANSWER:;;;
let defaults = UserDefaults.standard
override func viewDidLoad() {
super.viewDidLoad()
if let switchValue = getSwitchValue(), switchValue {
switchOutlet.setOn(true, animated: true)
} else {
switchOutlet.setOn(false, animated: true)
}
}
#IBAction func Switch(_ sender: UISwitch) {
if sender.isOn == false {
setSwitchStatus(status: false)
sender.setOn(false, animated: true)
} else if sender.isOn == true {
setSwitchStatus(status: true)
sender.setOn(true, animated: true)
}
}
func setSwitchStatus(status: Bool?) {
if status != nil {
defaults.set(status, forKey: "save1")
}
}
func getSwitchValue() -> Bool? {
return defaults.bool(forKey: "save1")
}
I'm not sure this is what you're looking for but I'd do it like this:
let defaults = UserDefaults.standard
#IBOutlet mySwitch: UISwitch!
//or any other function that is called 'when the app is reopened'
override func viewDidAppear() {
self.mySwitch.setOn(defaults.bool(forKey: "switchDefaultsKey"), animated: true)
}
#IBAction func switchAction(_ sender: UISwitch) {
defaults.set(sender.isOn, forKey: "switchDefaultsKey")
}

How should I set button's image in same action?

In my ViewController,
there is multiple buttons connected to the same action
my button is like check or uncheck
I have tried below
My action is triggered, but image didn't change
var uncheckBoxImage = UIImage(named: "uncheckBox")
var checkBoxImage = UIImage(named: "checkBox")
override func viewDidLoad() {
super.viewDidLoad()
for button in buttons{
button?.setImage(uncheckBoxImage, for: .normal)
//every button I set uncheckBoxImage first.
}
}
#IBAction func btnAction(_ sender: UIButton) { //connect every button
if sender.imageView == checkBoxImage {
sender.setImage(uncheckBoxImage, for: .normal)
}else {
sender.setImage(checkBoxImage, for: .normal)
}
}
I also tried below, but it can't process multiple button
var cube:Bool = false
#IBAction func btnAction(_ sender: Any) {
cube = !cube
if cube {
sender.setImage(checkBoxImage, for: .normal)
} else {
sender.setImage(uncheckBoxImage, for: .normal)
}
}
How should I fix these situation ?
Like it has some questions for you
And you just need to click to be check or click again to be uncheck
The trick is to use the selectedState for buttons.
Set both images for .normal and .selected state:
button?.setImage(uncheckBoxImage, for: .normal)
button?.setImage(checkBoxImage, for: .selected)
then, in IBAction:
#IBAction func btnAction(_ sender: UIButton) {
sender.isSelected = !sender.isSelected
...
}
You should implement different button's state, it will change image automatically
var uncheckBoxImage = UIImage(named: "uncheckBox")
var checkBoxImage = UIImage(named: "checkBox")
override func viewDidLoad() {
super.viewDidLoad()
for button in buttons{
button?.setImage(uncheckBoxImage, for: .normal)
button?.setImage(checkBoxImage, for: .selected)
}
}
#IBAction func btnAction(_ sender: UIButton) { //connect every button
sender.isSelected = !sender.isSelected
}
Hi Please try with a tintcolor if that works
var uncheckBoxImage = UIImage(named: "uncheckBox")
var checkBoxImage = UIImage(named: "checkBox")
override func viewDidLoad() {
super.viewDidLoad()
for button in buttons{
button?.setImage(uncheckBoxImage, for: .normal)
button?.tintColor = UIColor.clear
}
}
#IBAction func btnAction(_ sender: UIButton) {
if sender.tintColor == UIColor.clear {
sender.setImage(checkBoxImage, for: .normal)
sender.tintColor = UIColor.green
}else if sender.tintColor == UIColor.green {
sender.setImage(uncheckBoxImage, for: .normal)
sender.tintColor = UIColor.clear
}
}
For just two states, abstracting "normal" and "selected", it's better to use the above answers, but if you need to handle multiple cases, you can use <#UIButton#>.currentImage!.isEqual(to: foo), to compare images and use only .normal state.
This is an example:
#IBAction func btnAction(_ sender: UIButton) {
if sender.currentImage != nil && sender.currentImage!.isEqual(UIImage(named: "a")) {
sender.setImage(UIImage(named: "b"), for: .normal)
} else {
sender.setImage(UIImage(named: "a"), for: .normal)
}
}
If you want multiple selection then you can use.
override func viewDidLoad() {
super.viewDidLoad()
for button in buttons {
button.setImage(UIImage(named: "uncheckBox"), for: .normal)
button.setImage(UIImage(named: "checkBox"), for: .selected)
button.tintColor = .clear
}
}
#IBAction func btnAction(_ sender: UIButton) {
// toggle automatic changes selection state
sender.isSelected.toggle()
}

how to change a UIbutton in a collection view?

I have a collection view with a like button on each. I also have a refresh button, although I do not know if it is relevant.
How do I change the image of the button after it is pressed?
I tried adding this, but nothing happens:
#IBOutlet weak var likeNot: UIButton!
#IBAction func likeIt(_ sender: UIButton) {
func viewDidLoad() {
super.viewDidLoad()
self.likeNot.setImage(UIImage(imageLiteralResourceName: "like"), for: .normal)
self.likeNot.setImage(UIImage(imageLiteralResourceName: "likeSelected"), for: .selected)
// likeIt.setImage(UIImage(named: "likeSelected"), for: .highlighted)
}
}
I also have a refresh button. Will that interferes?
#IBAction func refresh_TouchUpInside(_ sender: Any) {
loadTopPosts()
}
func loadTopPosts() {
ProgressHUD.show("Loading...", interaction: false)
self.posts.removeAll()
self.collectionView.reloadData()
Api.Post.observeTopPosts { (post) in
self.posts.append(post)
self.collectionView.reloadData()
ProgressHUD.dismiss()
}
}
Your likeIt(_:) function is not doing anything because you're only defining another function for some reason inside of it (viewDidLoad). Just call setImage(_:for:) on the buttons without the inner function:
#IBAction func likeIt(_ sender: UIButton) {
self.likeNot.setImage(UIImage(imageLiteralResourceName: "like"), for: .normal)
self.likeNot.setImage(UIImage(imageLiteralResourceName: "likeSelected"), for: .selected)
// likeIt.setImage(UIImage(named: "likeSelected"), for: .highlighted)
}

how to save the state of radio button?

i am trying to save the state of my radio button but it doesn't working for me any idea how to do that? i am using userdefaults for that now
class WTSettingsVC: UIViewController {
#IBOutlet weak var checkBttn: DLRadioButton!
#IBOutlet weak var checkBttn2: DLRadioButton!
var switchON : Bool = false
var button : Bool = false
let defaults = UserDefaults.standard
override func viewDidLoad() {
super.viewDidLoad()
checkBttn.isSelected = UserDefaults.standard.bool(forKey: "issaved")
checkBttn2.isSelected = UserDefaults.standard.bool(forKey: "issaved")
}
override func viewWillAppear(_ animated: Bool) {
super .viewWillAppear(animated)
self.setCommonNavigationBar(title: "Settings", largeTitle: true, tranpernt: false, tint: WTConstant.LMColors.greenTheme, fontColor: .white)
checkBttn?.isEnabled = UserDefaults.standard.bool(forKey: "switchState")
checkBttn?.addTarget(self, action: #selector(bttnAction(_:)), for: .touchUpInside)
}
#IBAction func bttnAction(_ sender: DLRadioButton) {
if sender.tag == 1 {
sender.isEnabled = true
switchON = true
defaults.set(switchON, forKey: "switchON")
}else if sender.tag == 2{
sender.isEnabled = true
switchON = false
defaults.set(switchON, forKey: "switchON")
}
}
}
UserDefaults.standard.set(sender.isEnabled, forKey: "switchState")
UserDefaults.standard.synchronize()
}
}
Don't use the same key to store state of two buttons. And use same key for storing and retrieving the state of a button.
class WTSettingsVC: UIViewController {
#IBOutlet weak var checkBttn: DLRadioButton!
#IBOutlet weak var checkBttn2: DLRadioButton!
override func viewDidLoad() {
super.viewDidLoad()
checkBttn.isSelected = UserDefaults.standard.bool(forKey: "checkBttnSelected")
checkBttn2.isSelected = UserDefaults.standard.bool(forKey: "checkBttn2Selected")
checkBttn.addTarget(self, action: #selector(bttnAction(_:)), for: .touchUpInside)
checkBttn2.addTarget(self, action: #selector(bttnAction(_:)), for: .touchUpInside)
}
#IBAction func bttnAction(_ sender: DLRadioButton) {
if sender == checkBttn {
UserDefaults.standard.set(true, forKey: "checkBttnSelected")
UserDefaults.standard.set(false, forKey: "checkBttn2Selected")
}else if sender == checkBttn2 {
UserDefaults.standard.set(false, forKey: "checkBttnSelected")
UserDefaults.standard.set(true, forKey: "checkBttn2Selected")
}
}
}
It seems that your code is pretty obviously nested improperly. For example, the following code isn't actually executing in the bttnAction function:
UserDefaults.standard.set(sender.isEnabled, forKey: "switchState")
UserDefaults.standard.synchronize()
This code needs to be placed within the curly bracket above it. Try rewriting your code similarly to this:
class WTSettingsVC: UIViewController {
#IBOutlet weak var checkBttn: DLRadioButton!
#IBOutlet weak var checkBttn2: DLRadioButton!
var switchON : Bool = false
var button : Bool = false
let defaults = UserDefaults.standard
override func viewDidLoad() {
super.viewDidLoad()
checkBttn.isSelected = UserDefaults.standard.bool(forKey: "issaved")
checkBttn2.isSelected = UserDefaults.standard.bool(forKey: "issaved")
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.setCommonNavigationBar(title: "Settings", largeTitle: true, tranpernt: false, tint: WTConstant.LMColors.greenTheme, fontColor: .white)
checkBttn?.isEnabled = UserDefaults.standard.bool(forKey: "switchState")
checkBttn?.addTarget(self, action: #selector(bttnAction(_:)), for: .touchUpInside)
}
#IBAction func bttnAction(_ sender: DLRadioButton) {
if sender.tag == 1 {
sender.isEnabled = true
switchON = true
defaults.set(switchON, forKey: "switchON")
} else if sender.tag == 2 {
sender.isEnabled = true
switchON = false
defaults.set(switchON, forKey: "switchON")
}
UserDefaults.standard.set(sender.isEnabled, forKey: "switchState")
UserDefaults.standard.synchronize()
}
}
Because these lines of code were outside of the closing bracket for that function, the lines weren't actually included in any function and, thus, would never be called.

Changing image of UIButton via click - Swift

Im getting an error with this code..
What it should do: When user taps button, the image changes to checked, taps again, changes to Unchecked.
Im getting the error: AnyObject doesnt have member names 'setImage ...
#IBAction func tick(sender: AnyObject) {
if let image = UIImage(named:"Unchecked") {
sender.setImage(UIImage(named:"Checked.png"), forControlState: .Normal)
}
if let image = UIImage(named:"Checked") {
sender.setImage( UIImage(named:"Unchecked.png"), forControlState: .Normal)
}
}
You only needs to change (sender:AnyObject) to (sender:UIButton)
as below
#IBAction func tick(sender: UIButton) {
if let image = UIImage(named:"Unchecked") {
sender.setImage(UIImage(named:"Checked.png"), forControlState: .Normal)
}
if let image = UIImage(named:"Checked") {
sender.setImage( UIImage(named:"Unchecked.png"), forControlState: .Normal)
}
}
You have to explicitly tell your compiler that sender is a UIButton and not AnyObject type.
#IBAction func tick(sender: AnyObject) {
if let button = sender as! UIbutton {
if let image = UIImage(named:"Unchecked") {
button.setImage(UIImage(named:"Checked.png"), forControlState: .Normal)
}
if let image = UIImage(named:"Checked") {
button.setImage( UIImage(named:"Unchecked.png"), forControlState: .Normal)
}
}
}
You can do it this way:
var checked = false
#IBAction func tick(sender: UIButton) {
if checked {
sender.setImage( UIImage(named:"Unchecked.png"), forState: .Normal)
checked = false
} else {
sender.setImage(UIImage(named:"Checked.png"), forState: .Normal)
checked = true
}
}