I have a TabBar Application and I'm trying to set up a favorites tab.
I have managed to create a button and to send the favorited cell to the tab but right now if i add to favorites they are added correctly into the favorites tab but if i quit the app it doesn't save the favorites . How can i save the favorited cells in the favorite tab? would UserDefault do the best job? and if so how can it be done...
This is how i set up my favorite button :
//create a new button
let Favoritebutton: UIButton = UIButton(type: UIButtonType.custom)
//set image for button
Favoritebutton.setImage(UIImage(named: "EmptyHeart.png"), for: .normal)
Favoritebutton.setImage(UIImage(named: "FilledHeart.png"), for: .selected)
//add function for button
Favoritebutton.addTarget(self, action: #selector(self.button), for: .touchUpInside)
//set frame
Favoritebutton.frame = CGRect(x:0,y: 0,width: 35,height: 35)
Favoritebutton.isSelected = UserDefaults.standard.bool(forKey: "isSaved")
let barButton = UIBarButtonItem(customView: Favoritebutton)
//assign button to navigationbar
self.navigationItem.rightBarButtonItem = barButton
}
#IBAction func button(sender: UIButton) {
let newValue = !sender.isSelected
sender.isSelected = newValue
UserDefaults.standard.set(newValue, forKey: "isSaved")
let tabItem = self.tabBarController?.tabBar.items![3]
sel_val = tabItem?.badgeValue
if(sel_val == nil){
sel_val = "0"
}
let sel_num = Int(sel_val!)
let fav: NSMutableArray = []
fav.add(barImage)
fav.add(barName)
fav.add(streetName)
if sender.isSelected {
tabItem!.badgeValue = String(format: "%d", sel_num! + 1)
favorite.add(fav)
} else {
tabItem!.badgeValue = String(format: "%d", sel_num! - 1)
favorite.remove(fav)
}
}
#Newbie - I think you are not checking, second time when app open what is your favourite tab with your NSUserDefault.
Related
In the following code I have a couple buttons showing as an inputAccessoryView when inputFieldOne is in editing mode, when you tap First Button, it inputs ONE inside inputFieldOne and when I tap Second Button it inputs TWO inside inputFieldOne. It works as expected but what I would like to be able to do is re-use these buttons in multiple UITextFields. In other words, if I have another UTTextField called inputFieldTwo, I would like to be able to also input the values from those buttons when they're tapped.
How can I keep track of what UITextField is currently in editing mode so I can append the values from the buttons?
#IBOutlet weak var inputFieldOne: UITextField!
#IBOutlet weak var inputFieldTwo: UITextField!
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
addButtonsToKeyboard()
}
func addButtonsToKeyboard(){
// First button
let button1 = UIButton()
button1.setTitle("First Button", for: UIControl.State())
button1.addTarget(self, action: #selector(buttonKeyPress), for: UIControl.Event.touchUpInside)
let barButton1 = UIBarButtonItem()
barButton1.customView = button1
// Second button
let button2 = UIButton()
button2.setTitle("Second Button", for: UIControl.State())
button2.addTarget(self, action: #selector(buttonKeyPress), for: UIControl.Event.touchUpInside)
let barButton2 = UIBarButtonItem()
barButton2.customView = button2
/// UIToolbar.
let toolBar = UIToolbar()
toolBar.tintColor = UIColor.blue
toolBar.barTintColor = UIColor.red
toolBar.items = [barButton1, barButton2]
toolBar.sizeToFit()
inputFieldOne.inputAccessoryView = toolBar
}
#objc func buttonKeyPress(_ sender: UIButton){
switch sender.currentTitle!{
case "First Button":
inputFieldOne.text = "ONE"
case "Second Button":
inputFieldOne.text = "TWO"
default: break
}
}
There are many ways to make it reusable as i have very limited time so i suggest you can do it with Extension
You can use it for you all textfield
So here is the code snippet:
extension UITextField
{
// you can pass here array of UIbarbutton also
func addButtonsToKeyboard(){
// First button
let button1 = UIButton()
button1.setTitle("First Button", for: UIControl.State())
button1.addTarget(self, action: #selector(buttonKeyPress), for: UIControl.Event.touchUpInside)
let barButton1 = UIBarButtonItem()
barButton1.customView = button1
// Second button
let button2 = UIButton()
button2.setTitle("Second Button", for: UIControl.State())
button2.addTarget(self, action: #selector(buttonKeyPress), for: UIControl.Event.touchUpInside)
let barButton2 = UIBarButtonItem()
barButton2.customView = button2
/// UIToolbar.
let toolBar = UIToolbar()
toolBar.tintColor = UIColor.blue
toolBar.barTintColor = UIColor.red
toolBar.items = [barButton1, barButton2]
toolBar.sizeToFit()
self.inputAccessoryView = toolBar
}
#objc func buttonKeyPress(_ sender: UIButton){
switch sender.currentTitle!{
case "First Button":
self.text = "ONE"
case "Second Button":
self.text = "TWO"
default: break
}
}
}
And with you textfield object you can add it with below code
txtSwift.addButtonsToKeyboard()
Hope it help you!!!
My vc contains:
-1 name textView
-1 label // for flavors
-2 radio buttons // yes and no
-1 nextButton
What I want to do is keep the nextButton disabled until the textView is filled out, the label's text value is changed from its initial title of "Pick a Flavor" to whatever flavor they pick, and 1 of the radio buttons are selected.
I know using a textView's textViewDidEndEditing() I can listen to changes on it after the user finishes editing disable or enable the nextButton.
func textViewDidEndEditing(_ textView: UITextView) {
handleTextInputChanged()
}
#objc func handleTextInputChanged() {
let isFormValid = nameTextView.text?.count ?? 0 > 0
if isFormValid {
nextButton.isEnabled = true
nextButton.backgroundColor = .red
} else {
nextButton.isEnabled = false
nextButton.backgroundColor = .lightgray
}
}
How would I additionally disable or enable the nextButton based on wether or not one of the radio buttons were selected and the label's text is changed in addition to checking the nameTextView has text inside of it?
FYI the label's text is initially set with "Pick a Flavor". I have a gesture recognizer hooked up to it and when its tapped a new vc with a tableView is presented. The user picks a flavor, a protocol sends it back to this vc and the label's text will change to whatever flavor was selected (eg the label's title would say "Butter Pecan" if chosen). The nextButton should be disabled as long as the label's title is still set to "Pick a Flavor".
code:
let flavorLabel: UILabel = {
let label = UILabel()
label.text = "Pick a Flavor"
label.isUserInteractionEnabled = true
return label
}()
let nameTextView: UITextView = {
let textView = UITextView()
return textView
}()
let noButton: DLRadioButton = {
let button = DLRadioButton(type: .custom)
button.setTitle("No", for: .normal)
button.setTitleColor(UIColor.lightGray, for: .normal)
button.addTarget(self, action: #selector(noButtonPressed), for: .touchUpInside)
return button
}()
let yesButton: DLRadioButton = {
let button = DLRadioButton(type: .custom)
button.setTitle("Yes", for: .normal)
button.setTitleColor(UIColor.lightGray, for: .normal)
button.addTarget(self, action: #selector(yesButtonPressed), for: .touchUpInside)
return button
}()
let nextButton: UIButton = {
let button = UIButton(type: .system)
button.setTitle("Next", for: .normal)
button.setTitleColor(UIColor.white, for: .normal)
button.isEnabled = false
button.backgroundColor = .lightGray
button.addTarget(self, action: #selector(nextButtonTapped), for: .touchUpInside)
return button
}()
var choice: Bool?
override func viewDidLoad() {
super.viewDidLoad()
flavorVC.delegate = self
}
func textViewDidEndEditing(_ textView: UITextView) {
handleTextInputChanged()
}
#objc func handleTextInputChanged() {
let isFormValid = nameTextView.text?.count ?? 0 > 0
if isFormValid {
nextButton.isEnabled = true
nextButton.backgroundColor = .red
} else {
nextButton.isEnabled = false
nextButton.backgroundColor = .lightgray
}
}
#objc fileprivate func noButtonPressed() {
choice = false
}
#objc fileprivate func yesButtonPressed() {
choice = true
}
// delegate method from FlavorController
func selectedFlavor(flavor: String) {
flavorLabel.text = flavor // eg. "Butter Pecan"
}
You need to create a function that check all like this
func checkAll() {
nextButto.isEnabled = flavorLabel.text != "Pick a Flavor" &&
nameTextField.text != "" &&
(noButton.someProerty != || yesButton.someProerty != )
}
and call it from textfield and button targets plus
var ob:NSKeyValueObservation?
ob = flavorLabel.observe(\.text,options:[.new], changeHandler: { [unowned self] _, change in
self.checkAll()
}
I left the radio checks because both of them are custom , so you should know what to check , btw you can set tag of selected to 1 inside the target method and check according to it or some other logic you want
In my project I am using 6 buttons in one screen.I want to change the button color based on user's tap and "day order value". i am getting "day order value" from server.for example user day order value is equal to 1, day1 button background color should be red if user taps on day2 button day2 button should be in blue and remaining all button background colour should be white.
Please see the below screenshot.
if user pressed on one button that particular button should be highlight with some color remaining buttons should be same color. I can able to change button color by checking each condition but I want to write in simple manner.
see the following code which i have i tried for "dayoredrvalue".
func UpdateButtoncolor()
{
let dayOrderStr = UserDefaults.standard.string(forKey: "dayOrderStr")
print("dayOrderStr--",dayOrderStr)
if (dayOrderStr?.isEqual("1"))!{
self.day1Btn.backgroundColor = UIColor.red
self.day2Btn.backgroundColor = UIColor.white
self.day3Btn.backgroundColor = UIColor.white
self.day4Btn.backgroundColor = UIColor.white
self.day5Btn.backgroundColor = UIColor.white
self.day6Btn.backgroundColor = UIColor.white
}else if(dayOrderStr?.isEqual("2"))!
{
self.day1Btn.backgroundColor = UIColor.white
self.day2Btn.backgroundColor = UIColor.red
self.day3Btn.backgroundColor = UIColor.white
self.day4Btn.backgroundColor = UIColor.white
self.day5Btn.backgroundColor = UIColor.white
self.day6Btn.backgroundColor = UIColor.white
}else if(dayOrderStr?.isEqual("3"))!
{
self.day1Btn.backgroundColor = UIColor.white
self.day2Btn.backgroundColor = UIColor.white
self.day3Btn.backgroundColor = UIColor.red
self.day4Btn.backgroundColor = UIColor.white
self.day5Btn.backgroundColor = UIColor.white
self.day6Btn.backgroundColor = UIColor.white
}else if(dayOrderStr?.isEqual("4"))!
{
self.day1Btn.backgroundColor = UIColor.white
self.day2Btn.backgroundColor = UIColor.white
self.day3Btn.backgroundColor = UIColor.white
self.day4Btn.backgroundColor = UIColor.red
self.day5Btn.backgroundColor = UIColor.white
self.day6Btn.backgroundColor = UIColor.white
}else if(dayOrderStr?.isEqual("5"))!
{
self.day1Btn.backgroundColor = UIColor.white
self.day2Btn.backgroundColor = UIColor.white
self.day3Btn.backgroundColor = UIColor.white
self.day4Btn.backgroundColor = UIColor.white
self.day5Btn.backgroundColor = UIColor.red
self.day6Btn.backgroundColor = UIColor.white
}else
{
self.day1Btn.backgroundColor = UIColor.white
self.day2Btn.backgroundColor = UIColor.white
self.day3Btn.backgroundColor = UIColor.white
self.day4Btn.backgroundColor = UIColor.white
self.day5Btn.backgroundColor = UIColor.white
self.day6Btn.backgroundColor = UIColor.red
}
}
As per your query, It's quite simple. Just follow the following -
Step 1: Add an UIButton object in your viewController. Like that -
var selectedButton: UIButton? = nil
Step 2: Add same button Action for all your buttons -
#IBAction func btnActionSelection(_ sender:UIButton){
if(selectedButton == nil){ // No previous button was selected
updateButtonSelection(sender)
}else{ // User have already selected a button
if(selectedButton != sender){ // Not the same button
selectedButton?.backgroundColor = .clear
updateButtonSelection(sender)
}
}
}
Step 3: Now, Update button selection
func updateButtonSelection(_ sender: UIButton){
UserDefaults.standard.set("\(sender.tag)", forKey: "dayOrderStr")
selectedButton = sender
selectedButton?.backgroundColor = .green
}
Step 4: Check User selected day (For that you need to add tag on buttons from 1 to 6 respectively)
override func viewDidLoad() {
super.viewDidLoad()
// Check user's selected day
if let selectedDay = UserDefaults.standard.value(forKey: "dayOrderStr") as? String{
debugPrint("selectedDay: "selectedDay) // Get user's selected day
if let btn = self.view.viewWithTag(Int(selectedDay)!){
updateButtonSelection(btn)
}
}
//Other stuff
}
I have attached a demo for you using my logic:
For this you need to take a Group Outlets of your UIButton and assign a unique tag to each and then rest logic is described in the demo attached below.
like
#IBOutlet var btnAllSelected: [UIButton]!
And then simple logic like this:
#IBAction func btnAllClicked(_ sender: UIButton) {
for button in btnAllSelected {
if sender.tag == button.tag{
button.isSelected = true;
button.backgroundColor = UIColor.green
}else{
button.isSelected = false;
button.backgroundColor = UIColor.red
}
}
if sender.tag == 1{
print("Button 1 selected")
}else if sender.tag == 2{
print("Button 2 selected")
}else if sender.tag == 3{
print("Button 3 selected")
}else if sender.tag == 4{
print("Button 4 selected")
}else if sender.tag == 5{
print("Button 5 selected")
}else if sender.tag == 6{
print("Button 6 selected")
}
}
Link to the Demo
FYI:- Please ignore the pods installed in it. I edited some another demo and made a one for you.
Hope this helps.
You should create New Referencing Outlet Collections for all your UIButtons like this,
#IBOutlet var arrButtons: [UIButton]!
Implement only one Button tap events for all your buttons, Please find belo code.
#IBAction func btnClicked(_ sender: UIButton) {
arrButtons.forEach({$0.backgroundColor = UIColor.red})
sender.backgroundColor = UIColor.darkGray
}
Simplified code, it uses an array of the buttons and an index:
let buttonArray = [day1Btn, day2Btn, day3Btn, day4Btn, day5Btn, day6Btn]
buttonArray.forEach { $0.backgroundColor = .white }
guard let dayOrderStr = UserDefaults.standard.string(forKey: "dayOrderStr"),
let dayOrderIndex = Int(dayOrderStr), 1...buttonArray.count ~= dayOrderIndex {
buttonArray[dayOrderIndex-1].backgroundColor = .red
}
It can be still simpler if you save the value in UserDefaults as Int
Here is one solution among many others.
#IBOutlet var buttons: [UIButton]! // link all the buttons from the storyboard
func changeColorButton(sender: UIButton) {
// default appearance for all buttons
for button in buttons {
button.backgroundColor = UIColor.green
}
// update color only for the button clicked
sender.backgroundColor = .orange
}
#IBAction func buttonTapped(_ sender: UIButton) {
updateFocusPicture(sender: sender)
}
I'm trying to complete my favorite button by saving it state even when i quit the view \ App . it will be great if anyone could show me how can i do this, I'm using Xcode 8 and coding with Swift 3.
Current Button Code :
//create a new button
let Favoritebutton: UIButton = UIButton(type: UIButtonType.custom)
//set image for button
Favoritebutton.setImage(UIImage(named: "EmptyHeart.png"), for: .normal)
Favoritebutton.setImage(UIImage(named: "FilledHeart.png"), for: .selected)
//add function for button
Favoritebutton.addTarget(self, action: #selector(self.button), for: .touchUpInside)
//set frame
Favoritebutton.frame = CGRect(x:0,y: 0,width: 35,height: 35)
let barButton = UIBarButtonItem(customView: Favoritebutton)
//assign button to navigationbar
self.navigationItem.rightBarButtonItem = barButton
let state = UserDefaults.standard.bool(forKey: "isSaved") ?? false
}
#IBAction func button(sender: UIButton) {
sender.isSelected = !sender.isSelected
UserDefaults.standard.set(true,forKey: "isSaved")
UserDefaults.standard.synchronize()
if let Favoritebutton = sender as? UIButton {
if Favoritebutton.isSelected {
// set selected
Favoritebutton.isSelected = true
UserDefaults.standard.set(true, forKey: "MY_FAV_KEY")
UserDefaults.standard.synchronize()
// set badge to tabbar item.
let tabItem = self.tabBarController?.tabBar.items![3]
sel_val = tabItem?.badgeValue
if(sel_val == nil){
sel_val = "0"
}
let sel_num = Int(sel_val!)
tabItem!.badgeValue = String(format: "%d", sel_num! + 1) as String
let Fav: NSMutableArray = []
Fav.add(barImage)
Fav.add(barName)
Fav.add(streetName)
favorite.add(Fav)
} else {
// set deselected
Favoritebutton.isSelected = false
UserDefaults.standard.set(true, forKey: "MY_FAV_KEY")
UserDefaults.standard.synchronize()
let tabItem = self.tabBarController?.tabBar.items![3]
sel_val = tabItem?.badgeValue
if(sel_val == nil){
sel_val = "0"
}
let sel_num = Int(sel_val!)
tabItem!.badgeValue = String(format: "%d", sel_num! - 1) as String
let Fav: NSMutableArray = []
Fav.add(barImage)
Fav.add(barName)
Fav.add(streetName)
favorite.remove(Fav)
}
}
As i said,It will be great if anyone could help me save the button's state
even if i quit the view or app , i would really appreciate it, Thank you in advance !
Saving the value to UserDefaults writes it out to the plist file. It does not read the value back in or restore state when the app resumes. You are responsible for that. So somewhere in viewDidLoad check the state:
let state = UserDefaults.standard.bool(forKey: "isSaved") ?? false
Then set your button accordingly
I'm starting to create a favorite button for my project and i need some help...
I have created a button and already programmed it to switch image when tapped right here:
override func viewDidLoad() {
super.viewDidLoad()
//create a new button
let Favoritebutton: UIButton = UIButton(type: UIButtonType.Custom)
//set image for button
Favoritebutton.setImage(UIImage(named: "EmptyHeart.png"), forState: UIControlState.Normal)
Favoritebutton.setImage(UIImage(named: "FilledHeart.png"), forState: UIControlState.Selected)
//add function for button
Favoritebutton.addTarget(self, action: #selector(self.button(_:)), forControlEvents: .TouchUpInside)
//set frame
Favoritebutton.frame = CGRectMake(90, 90, 35, 35)
let barButton = UIBarButtonItem(customView: Favoritebutton)
//assign button to navigationbar
self.navigationItem.rightBarButtonItem = barButton
}
#IBAction func button(sender: UIButton) {
sender.selected = !sender.selected;
}
It works perfectly but as of right now if i quit the app the button does NOT save the status if its selected or not . I heard you can achieve this with NSUserDefault but i don't know how to implement this so i would love to get some help with it :)
I am using Swift 2.3 and Xcode 8.
Thank you.
It's quite easy. In UserDefaults you can store boolean value without any problem.
In viewDidLoad you check value for your key like this.
let defaults = UserDefaults.standard
let buttonIsSelected = defaults.bool(forKey: "keyForIsButtonSelected") // If no value exists for this key then false is returned
button.selected = buttonIsSelected
Inside your button function remember to save your status.
sender.selected = !sender.selected
let defaults = UserDefaults.standard
defaults.set(sender.selected, forKey: "keyForIsButtonSelected")
defaults.synchronize() // Save your defaults, can also move this part of code to applicationWillTerminate
For Swift 2.3 use this.
let defaults = NSUserDefaults.standardUserDefaults()
let buttonIsSelected = defaults.boolForKey("keyForIsButtonSelected") // If no value exists for this key then false is returned
button.selected = buttonIsSelected
Inside button function.
sender.selected = !sender.selected
let defaults = NSUserDefaults.standardUserDefaults()
defaults.setBool(sender.selected, forKey: "keyForIsButtonSelected")
defaults.synchronize() // Save your defaults, can also move this part of code to applicationWillTerminate
for swift 3 it will be next:
//save value
UserDefaults.standard.set(selected, forKey: "lButtonSelected")
//then on next launch restore it
let selected = UserDefaults.standard.value(forKey: "lButtonSelected")
To save the value in NSUserDefaults:
UserDefaults.standard.set(selected, forKey: "buttonStatus")
UserDefaults.standard.synchronize()
And to retrieve the value from NSUserDefaults:
let buttonStatus = UserDefaults.standard.value(forKey: "buttonStatus")