Save checkbox button state using userdefaults in swift - ios

view controller had two check boxes buttons
1.chekcIn
2.checkOut
am saving the checkIN [ checkbox button] status in user defaults, working fine but when am using that userdefaults key in Nextviewcontroller its always showing true and not running into false block
this is the code
inHomeview controller
#IBAction func CheckInButtonClick(_ sender: UIButton) {
for senderdata in checkINOUT {
senderdata.setImage( UIImage(named:"uncheck1"), for: .normal)
print("uncheck is called")
}
sender.setImage(UIImage(named:"check1"), for: .normal)
prefs.set(true, forKey: "check")
prefs.synchronize()
}
nextviewcontroller
override func viewDidLoad() {
super.viewDidLoad()
{
let prefs:UserDefaults = UserDefaults.standard
if prefs.bool(forKey: "check") ==true
{
print("select")
} else {
print("unselect")
}
}
check box select its execute main block if unselect execute else block
how to over come this problem where I did mistake

You´re not setting your userDefault value to false. You´re only setting it to true, that´s why it´s always true. And btw no need to use synchronize() Change your code to the following instead:
HomeViewController:
#IBAction func CheckInButtonClick(_ sender: UIButton) {
for senderdata in checkINOUT {
senderdata.setImage( UIImage(named:"uncheck1"), for: .normal)
print("uncheck is called")
}
sender.setImage(UIImage(named:"check1"), for: .normal)
UserDefaults.standard.set(true, forKey: "check")
}
NextViewController:
override func viewDidLoad() {
super.viewDidLoad()
if UserDefaults.standard.bool(forKey: "check") {
print("select")
} else {
print("unselect") {
}
}
So do check where you want to set your check value to false and use it.
Update:
Just do this check:
if UserDefaults.standard.set(true, forKey: "check") {
// Show data
} else {
// segue to another viewController
}

When you set "check" value as true once, it will always true, until you set "check" value to false.
I think you should add some code to set "check" to false, when user not select the checkbox.

Related

Save UISwitch's toggled data in UserDefaults

I've declared a boolean with default value true, if my UISwitch is on I want boolean variable to be true else false, my code works fine until I try to store that boolean in UserDefaults when I reset the xCode Simulator I check with print method but it is not really saved...
any solution will be appericated.
var userDefaultSamarxvo:Bool = true
let defaults = UserDefaults.standard
override func viewDidLoad() {
super.viewDidLoad()
defaults.set(userDefaultSamarxvo,forKey: "Samarxvo") // set of userdefault
if userDefaultSamarxvo {
print("hello")
}else{
print("olleh")
}
}
#IBAction func samarxvoDidChange(_ sender: UISwitch) {
if sender.isOn {
userDefaultSamarxvo.toggle()
print("samarxo")
}else{
userDefaultSamarxvo.toggle()
print("samarxo 1 ")
}
}
In viewDidLoad you want to load the saved value from user defaults. When the switch changes you need to save the new value to user defaults.
Setting a local variable (userDefaultSamarxvo) doesn't change what is stored in the user defaults; Local variables don't bind to user defaults storage.
There is an added complication; bool(forKey) will return false if there is no value for the key in UserDefaults. If you want the initial value to be true then you need to handle that in some way. You can use object(forKey) which returns an optional
var userDefaultSamarxvo:Bool = true {
didSet {
UserDefaults.standard.set(userDefaultSamarxvo, forKey:switchKey)
}
}
let defaults = UserDefaults.standard
let switchKey = "Samarxvo"
#IBOutlet weak var theSwitch: UISwitch!
override func viewDidLoad() {
super.viewDidLoad()
if defaults.object(forKey: switchKey) != nil {
userDefaultSamarxvo = defaults.bool(forKey: switchKey)
}
self.theSwitch.isOn = userDefaultSamarxvo
}
#IBAction func samarxvoDidChange(_ sender: UISwitch) {
userDefaultSamarxvo = sender.isOn
}
I have used a didSet clause to update the user defaults value when the property changes.

How to assign different actions for same UIButton?

while click on the button for the first time, the title of the button will get changed from "Add to Cart" to "Go to Cart". And from the next click the button will navigate to the next screen (cart page) [just like flipkart].
here is my piece of code:
#IBAction func addToCartbtnTapped(_ sender: Any) {
if let info = detailInfo {
let cartData = CartStruct(cartItems: info, cartQuantity: 1)
self.saveCart(data: cartData)
showAlert()
(sender as AnyObject).setTitle("Go to Cart", for: .normal)
let cart = self.storyboard?.instantiateViewController(withIdentifier: "CartViewController") as? CartViewController
self.navigationController?.pushViewController(cart!, animated: true)
}
}
I'm able to change the title of the button. But whenever I click on the button for nth number of time also, the product is getting added to the cart, screen is not navigating.
How to solve this issue?
Update..
override func viewDidLoad() {
super.viewDidLoad()
UserDefaults.standard.string(forKey: "btn")
}
#IBAction func addToCartbtnTapped(_ sender: Any) {
if !Clicked {
if let info = detailInfo {
let cartData = CartStruct(cartItems: info, cartQuantity: 1)
self.saveCart(data: cartData)
showAlert()
addingTOCart.setTitle("Go to Cart", for: .normal)
UserDefaults.standard.set("Go to Cart", forKey: "btn")
print("Clicked")
Clicked = true
return
}
}
if Clicked {
print("Perform Action")
let cart = self.storyboard?.instantiateViewController(withIdentifier: "CartViewController") as? CartViewController
self.navigationController?.pushViewController(cart!, animated: true)
}
}
This is how I am trying to store the "Go to Cart" state. But not working.. please suggest!
Add this code to check cart is already added or not, If added change title according in your detail controller:
override func viewWillAppear(_ animated: Bool) {
if let info = detailInfo {
let buttonTItle = (self.checkCartData(cartInfo: info) ? "Go to Cart" : "Add to Cart")
addToCartButton.setTitle(buttonTItle, for: .normal)
}
}
Next, Check before adding to cart. If already added, will navigate to cart page else add new cart item(changing button title too).
#IBAction func addToCartbtnTapped(_ sender: Any) {
if let info = detailInfo {
if checkCartData(cartInfo: info) {
let cart = self.storyboard?.instantiateViewController(withIdentifier: "CartViewController") as? CartViewController
self.navigationController?.pushViewController(cart!, animated: true)
} else {
let cartData = CartStruct(cartItems: info, cartQuantity: 1)
self.saveCart(data: cartData)
showAlert()
(sender as AnyObject).setTitle("Go to Cart", for: .normal)
}
}
}
Check Cart data here:
func checkCartData(cartInfo: jsonstruct) -> Bool {
guard let cart = self.getCartData() else { return false }
return (cart.contains(where: { $0.cartItems.name == cartInfo.name }) ? true : false )
}
Get all Cart Data with this method:
func getCartData() -> [CartStruct]? {
let defaults = UserDefaults.standard
var tempCart: [CartStruct]?
if let cdata = defaults.data(forKey: "cartt") {
tempCart = try! PropertyListDecoder().decode([CartStruct].self, from: cdata)
}
return tempCart
}
You can apply check on your button title for performing two different actions. Also you are showing alert and pushing View Controller at the same time which might be the reason for screen not navigating.
#IBAction func addToCartbtnTapped(_ sender: UIButton) {
if let info = detailInfo {
switch sender.currentTitle! {
case "Add to Cart":
let cartData = CartStruct(cartItems: info, cartQuantity: 1)
self.saveCart(data: cartData)
showAlert()
(sender as AnyObject).setTitle("Go to Cart", for: .normal)
case "Go to Cart":
let cartData = CartStruct(cartItems: info, cartQuantity: 1)
self.saveCart(data: cartData)
showAlert()
(sender as AnyObject).setTitle("Go to Cart", for: .normal)
default:
print("Default Case")
}
}
}
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var btn: UIButton!
var Clicked:Bool = false
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
#IBAction func btnClick(_ sender: Any) {
if !Clicked {
btn.setTitle("Click", for: .normal)
print("Clicked")
Clicked = true
return
}
if Clicked {
print("Perform Action")
}
}
}

Check if playing then change icon on a button

I am currently using the following to change the button icon, when user has press a playVideo.
However, I need something that will check if the media is currently playing and update this with the correct icon?
I am wondering what is the best way to do this.
#IBAction func playVideo(_ sender: Any) {
if(defaultsKeys.musicplayer_connected == "1"){
self.defaults.set("0", forKey: defaultsKeys.musicplayer_connected)
// (sender as! UIButton).setTitle("Pause", for: [])
(sender as! UIButton).setBackgroundImage(UIImage(systemName: "pause.circle"), for: UIControl.State.normal)
MusicPlayer.shared.startBackgroundMusic()
}else
{
self.defaults.set("1", forKey: defaultsKeys.musicplayer_connected)
// (sender as! UIButton).setTitle("Play", for: [])
(sender as! UIButton).setBackgroundImage(UIImage(systemName: "play.circle"), for: UIControl.State.normal)
MusicPlayer.shared.stopBackgroundMusic()
//self.player.pause()
}
}
create a enum to store the state of the player
enum PlayerState {
case playing,paused
}
then create a property observer that will update your button on the change of the value
var playerStateChanged : PlayerState = .playing {
didSet {
switch playerStateChanged {
case .playing:
if #available(iOS 13.0, *) {
yourBtn.setBackgroundImage(UIImage(systemName: "play.circle"), for: .normal)
} else {
// Fallback on earlier versions
}
case .paused:
if #available(iOS 13.0, *) {
yourBtn.setBackgroundImage(UIImage(systemName: "pause.circle"), for: .normal)
} else {
// Fallback on earlier versions
}
}
}
}
Now in your IBAction, update the value of playerStateChanged and it will set the button image accordingly.
#IBAction func playVideo(_ sender: Any) {
// get if player is playing or not and set the value of playerStateChanged
playerStateChanged = .paused
}
You can create a Bool variable and configure the player's image and start/stop actions based on its current state.
Create a computed property isPlaying,
var isPlaying = false {
didSet {
self.playButton.setImage(UIImage(systemName: self.isPlaying ? "play.circle" : "pause.circle"), for: <#T##UIControl.State#>)
self.isPlaying ? MusicPlayer.shared.startBackgroundMusic() : MusicPlayer.shared.stopBackgroundMusic()
}
}
Now, in your playVideo(_:) action method, you need to simply change the state of isPlaying like so,
#IBAction func playVideo(_ sender: Any) {
self.isPlaying = !self.isPlaying
}

How to save the state of an UISwitch in SWIFT 4? [duplicate]

This question already has answers here:
How do i keep UISwitch state when changing ViewControllers?
(3 answers)
Closed 5 years ago.
I would like to save the State of an UISwitch after to change between View Controllers. Any help would be greatly appreciated!
I have a first View Controller with an UISwitch, to control the music in the background in different View Controllers:
#IBOutlet weak var SwitchMusic: UISwitch!
let defaults = UserDefaults.standard
var switchON : Bool = false
#IBAction func checkState(_ sender: UISwitch) {
if (sender.isOn == true)
{
switchON = true
defaults.set(switchON, forKey: "switchON")
MusicHelper.sharedHelper.playBackgroundMusic()
}
if (sender.isOn == false)
{
switchON = false
defaults.set(switchON, forKey: "switchON")
MusicHelper.sharedHelper.stopBackgroundMusic()
}
}
And a Second View Controller to load or no the music in the background if the switch is On or Off:
override func viewDidLoad() {
super.viewDidLoad()
if defaults.value(forKey: "switchON") != nil{
let switchON: Bool = defaults.value(forKey: "switchON") as! Bool
if switchON == true{
MusicHelper.sharedHelper.playBackgroundMusic()
}
else if switchON == false{
MusicHelper.sharedHelper.stopBackgroundMusic()
}
}
}
Also I have a class with the music:
class MusicHelper {
let defaults = UserDefaults.standard
static let sharedHelper = MusicHelper()
var musicBackgroundIntro:AVAudioPlayer = AVAudioPlayer()
func playBackgroundMusic() {
do {
let audioPath = Bundle.main.path(forResource: "Music", ofType: "mp3")
try musicBackgroundIntro = AVAudioPlayer(contentsOf: NSURL(fileURLWithPath: audioPath!) as URL)
musicBackgroundIntro.numberOfLoops = -1
musicBackgroundIntro.prepareToPlay()
musicBackgroundIntro.play()
} catch {
print("Cannot play the file")
}
}
func stopBackgroundMusic() {
musicBackgroundIntro.stop()
}
}
Now it is working perfectly the music in the background between View Controllers, and it is possible to turn off and on... but unfortunately do not save the current state of the UISwitch, and always when I enter in the First View Controller the state of the Switch is On.
Also any idea that how will be possible to apply in a Slider too?
Any help would be greatly appreciated!
Thanks
The easiest way for you would be to create a static var isSwitchOn: Bool = false
This state will be preserved between back and forth transitions.
You should reflect the state, if music is playing...
class MusicHelper {
public isPlaying: Bool {
get {
return musicBackgroundIntro.isPlaying
}
}
// your stuff here..
}
That way in other view controllers:
SwitchMusic.isOn = MusicHelper.sharedHelper.isPlaying
If you need other view controllers to update in response to this, you can add a delegate event (aka observer) if necessary.
Try something like that: Use the UISwitch as an #IBOutlet.
#IBOutlet weak var checkState: UISwitch!
override func viewDidLoad() {
super.viewDidLoad()
self.checkState.addTarget(self, action: #selector(action(sender:)), for: .valueChanged)
}
// Save state
func action(sender: UISwitch) {
let userDefaults = UserDefaults.standard
userDefaults.set(sender.isOn, forKey:"identifier")
}
// Retrieve state
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
let userDefaults = UserDefaults.standard.bool(forKey: "identifier")
self.checkState.setOn(userDefaults, animated: false)
}
You can give the switch a default value when it's created in viewcontroller1.
Assign the (default.value(forKey:"switchOn") as! Bool ) ?? false to that switch.

Button.titleLabel error in swift3

I am trying to compare the title that I have in a button so that if it is compared to another it does a certain thing or not. I'm using the .setTitle function but I think in swift3 it gives error and I can not find the why. Then I leave a catch of the error to make it easier to see it and also the code itself. Thanks for the help
#IBAction func _login_button(_ sender: Any)
{
if(_login_button.titleLabel?.text == "OKEY")
{
let preferences = UserDefaults.standard
preferences.removeObject(forKey: "session")
LoginToDo()
return
}
let username = _username.text
let password = _password.text
if(username == "" || password == "")
{
return
}
DoLogin(username!, password!)
}
change your #IBAction func _login_button(_ sender: Any) to you need to type cast from Any to UIButton #IBAction func _login_button(_ sender: UIButton)
#IBAction func _login_button(_ sender: UIButton)
{
if(sender.titleLabel?.text == "OKEY")
{
}
}
_login_button is #IBAction you have to create the button for #IBOutlet of button
you need to get button as below , now you access function name instead of sender
#IBAction func _login_button(_ sender: Any)
let button: UIButton = sender as! UIButton
if(button.titleLabel?.text == "OKEY")
{
}
}
If you get this error as per screen shot, you need to type cast from Any to UIButton and then use titleLabel property.

Resources