reusing of cell in table view causing button problems - ios

I have a button on my table view cell. I am returning numberOfRowsInSectionas return arrayname.count. therefore i get the same number of buttons as the array count.
I trigger a notification using that button, when the user presses that button again the notification gets canceled. It is a location based notification.
It works fine if if there is only one button in the table view. But when I return 2 or more cells, I can't seem to figure out how to distinguish between the button events without one affecting the other.
Example - there are two cells in the table and two buttons. One for location 'a' and one for location 'b'. I want a notification when i enter region 'a' so i press the button corresponding to location 'a'. but because button 'b' is not pressed the notification doesn't get scheduled. it works fine only if all the buttons are in the same state.
but,how can i solve this problem ?
`button.addTarget(self, action: "pressed:", forControlEvents: .TouchUpInside)
button.setImage(UIImage(named: "a.png")!, forState: .Normal)
button.tag = 999
func pressed(sender: UIButton!) {
if sender.tag == 999
{ sender.setImage(UIImage(named: "b.png")!, forState: .Normal)
sender.tag = 0 } else
{ sender.setImage(UIImage(named: "a.png")!, forState: .Normal) sender.tag = 999 }
}`
I am already using this code to switch images on button press.

I see no connection between the problem that you have and cell reusing.
The easiest way to detect which button is pressed is to add line:
button.tag = indexPath.row
to your cellForRowAtIndexPath function. Then in the function which is triggered by your buttons add:
func buttonPressed(sender:UIButton) {
let selectedItem = arrayname[sender.tag] // this gives you selected item from array
// or you can do
if sender.tag == 0 {
// button in first cell pressed
}
}

/*Buy settings the tag to your button you can identify which button is selected */
//create a button globally in your view controller
uibutton*menu
// add the below code in your cellForRowAtIndexPath method
[menus addTarget:self action:#selector(menuclick:) forControlEvents:UIControlEventTouchUpInside];
menus.tag=indexPath.row+1;
//identify button using button sender
(void)menuclick:(id)sender
{
NSInteger tagid=[sender tag];
if(checkbutton.isSelected)
{
//you can identify which button get selected
switch (tagid)
{
case 1:
//button 1 is selected
break;
case2:
//button 2 is selected
break;
default:
break;
}
[menu setSelected:NO];
}
else
{
//you can identify which button get unselected
switch (tagid)
{
case 1:
//button 1 is selected
break;
case2:
//button 2 is selected
break;
default:
break;
}
[menu setSelected:YES];
}
}

Related

When button pressed, button.setImage(nil) doesn't work

I'm trying to create Japanese crossword. Use buttons as cells. When trying to insert system image, it works (case mode 1). But when I choose other mode (2), the icon doesn't disappear.
let img1 = UIImage(systemName: "multiply"))
#IBAction func cellClicked(_ sender: UIButton) {
for cell in cellButtons {
if cell.tag == sender.tag {
switch typeCell { //when mode changes
case 1:
cell.setImage(img1, for: .normal) //work
default/*2*/:
cell.setImage(nil, for: .normal) //don't work, but running without errors
}
}
}
}
I was trying to use only sender (without if cell.tag == sender.tag; didn't work ), then create IBOutlet collection and run the code above.
Update:
I found and decide to use .isHidden. That works and I also solve my other issue :)
Thanks!

Swift handle favorite and unfavorite button based on JSON value

I am trying to implement favorite and unfavorite functionality into my cell. Here, Initially I am showing in collection view cell button icon favorite (gray), its mean unfavorite but after clicked the button it will show green, its mean favorite. From JSON I am getting response which cells are already favorite and others unfavorite icon. Its working fine but when I click JSON favorite enabled green button it’s not changing gray by single click, its working fine double click but every click I am calling JSON so 3rd click it will be add again favorite.
Here, below my code -
var checked = false
#IBAction func favoritesTapped(_ sender: Any) {
if checked {
favbutton.setImage(UIImage(named: "item_grayfav.png"), for: .normal)
checked = false
delegate?.unfavoriteButtonPressed(cell: self)
} else {
favbutton.setImage(UIImage(named: "item_greenfav.png"), for: .normal)
checked = true
delegate?.favoriteButtonPressed(cell: self)
}
}
Above code I am using for button click to change image and also initially I fixed gray checked = false
Into collection view cell at item
if indexPath.row < cfavoritesIDData.count {
if let i = cfavoritesIDData[indexPath.item] {
cell.favbutton.setImage(UIImage(named: "item_greenfav.png"), for: .normal)
}
else {
print("id is nil")
cell.favbutton.setImage(UIImage(named: "item_grayfav.png"), for: .normal)
}
}
Issues: If I click JSON enabled green button (favorite), its calling to unfavorite well but button icon not changing green after 3’rd click only its changing gray.
You need to store your cell model in your View Controller, the cell should not have a checked boolean, when you are configuring your cell in cellForRow: you should tell it there wether it is checked or not.
When pressing the button you should have a delegate callback or closure to tell the View Controller that the cell at IndexPath 'x' has pressed its favourite button and check the model as to wether or not the reaction would be checked or not, then reconfigure the cell again.
You can use the UIButton's selected property instead of checked variable:
if indexPath.row < favoritesIDData.count {
if let i = cfavoritesIDData[indexPath.item] {
cell.favbutton.setImage(UIImage(named: "item_greenfav.png"), for: .normal)
cell.favbutton.setSelected = true
}
else {
print("id is nil")
cell.favbutton.setImage(UIImage(named: "item_grayfav.png"), for: .normal)
cell.favbutton.setSelected = false
}
}
#IBAction func favoritesTapped(_ UIButton: favButton) {
if favButton.isSelected {
favbutton.setImage(UIImage(named: "item_grayfav.png"), for: .normal)
checked = false
delegate?.unfavoriteButtonPressed(cell: self)
} else {
favbutton.setImage(UIImage(named: "item_greenfav.png"), for: .normal)
checked = true
delegate?.favoriteButtonPressed(cell: self)
}
}
Note: Don't copy paste change according to correct syntax.

Deselect button (Radio Button) Swift 3 iOS

I am trying to make 2 buttons in Swift behave like Radio Buttons.
Each button has a different image for when they are Selected and Not Selected.
When I click one button, I want the other Button to go back to being in the "Not Selected" state and showing the "Not Selected" image if it was previously selected.
I'm using a switch statement:
func toggle(sender: UIButton) {
switch sender.tag {
case 1:
sender.isSelected = !sender.isSelected
case 2:
sender.isSelected = !sender.isSelected
default:
sender.isSelected = !sender.isSelected
}
}
This statement works for changing the buttons, but allows for both to be selected at the same time. How do I make it so that the other button is de-selected when you click the other one of the buttons?
You probably want to create outlets for you buttons then every time the toggle func is fired set both to unselected and then set the sender selected.
func toggle(sender: UIButton) {
//Sender is already selected no need to do anything
if sender.isSelected {
return
}
button1.isSelected = false
button2.isSelected = false
sender.isSelected = true
}

iOS UITableView : clear section button

I need to add clear button in table view section header. It is exactly same like the one in notification center. So when user clicks it, 'x' will change to 'Clear'. If s/he clicks it again, app will perform action. But any click outside this button, 'Clear' will be back to 'x'
How can I make this? Thanks in advance
Unfortunately this does not come out of the box. You have to create your own custom section header view. That custom header view contains a UILabel on the left side. On the right side you put a UIButton that has the title "X". When the user taps on the button, change its title to "Clear" and its state to .Selected. Only clear your table view section when the button is tapped and its state is .Selected:
func setupButton() {
let button = UIButton()
button.setTitle("X", forState: .Normal)
button.addTarget(self, action: Selector("didPressButton:"), forControlEvents: .TouchUpInside)
addSubview(button)
}
func didPressButton(button: UIButton) {
if button.selected {
// clear your table view section
}
button.setTitle("Clear", forState: .Normal)
button.selected = true
}
To put the button back in its unselected state add a background UIView to your section header view and add a UITapGestureRecognizer to it:
func setupBackground() {
let background = UIView()
let recognizer = UITapGestureRecognizer(target: self, action: Selector("didTapOutside:"))
background.addGestureRecognizer(recognizer)
insertSubview(background, belowSubview: button)
}
func didTapOutside(recognizer: UITapGestureRecognizer) {
button.selected = false
button.setTitle("X", forState: .Normal)
}
To use your custom section header in your table view you implement the following UITableViewDelegate method:
func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
// create your custom section header and return it
}

chnage image of button in swift everytime the user clicks on it

I have a button in a tableview cell. I want that initially the button has an image "A", when the user clicks on it, it changes to "B", when the user clicks on it again it changes back to "A".
Let the two images to be "A" and "B" in this scenario
Wherever the button is:
button.addTarget(self, action: "pressed:", forControlEvents: .TouchUpInside)
button.setImage(UIImage(named: "a.png")!, forState: .Normal)
button.tag = 999
func pressed(sender: UIButton!) {
if sender.tag == 999 {
sender.setImage(UIImage(named: "b.png")!, forState: .Normal)
sender.tag = 0
} else {
sender.setImage(UIImage(named: "a.png")!, forState: .Normal)
sender.tag = 999
}
}
You can add tag to the button.
// This code comes in viewDidLoad
button.tag = 1 // for A
button.titleLabel.text = "A"
// On-click of the button, check the tag and change the name
if button.tag == 1
{
button.tag = 2
button.titleLabel.text = "B"
}
Subclass UIButton, add click handler in this class and make reference in Interface Builder. Then, create boolean property in your class, which you will trigger in click handler every time. In didSet of this property set proper image
If we are just dealing with two states then this solution is easier and less messy. You can simply use UIButton states.
You can assign different images for default state and selected state in storyboard itself.
func pressed(sender:UIButton){
sender.selected = !sender.selected
}
This will just change the states and images will be displayed depending on state.

Resources