Handling button interaction of a dequeueReusableCell in iOS Swift - ios

I am making an iOS app that relies on a table view. In each cell of the table view, there are 4 buttons aligned on the bottom. I have a cell class that is pretty standard and a feedController to handle the table and setting all the items of the cell.
Everything works fine on it but I can not figure out how to handle the button clicks within the cell. I can hard code it into my cell class, but then every 3 cells has the same interaction. Is there a way to pass the button click function from the cell class into the controller? I have tried checking the state from the controller and that has not worked.

Can you add a gesture recognizer as you're doing your cellForItemAtIndexPath? So I had something similar with a collection view, and what I did was as it within:
func collectionView(collectionView: UICollectionView!, cellForItemAtIndexPath indexPath: NSIndexPath!) -> UICollectionViewCell!
{
var cell = collectionView.dequeueReusableCellWithReuseIdentifier("cell", forIndexPath: indexPath) as MyCollectionView
...
I would add a gesture recognizer to each cell
i.e.
cell.addGestureRecognizer(UITapGestureRecognizer(target: self, action:Selector("tapAction:")))
And then something like:
func tapAction(recognizer: UITapGestureRecognizer) {
...
}
so recognizer ends up being the specific item tapped, and I could take action accordingly (in my case, I had my datasource of items and I would find the item in an array by casting recognizer to a cell, finding the appropriate subview, and update values on it)

I would add code block properties to your cell class which the table can assign to deal with each button. In your cell, code each button handler to call the appropriate block, or pass an index for the button used in a single block.
See my answer here which has an example, but for a switch.
How can I get index path of cell on switch change event in section based table view

If after a few cells you get the same interaction, it's possibly because you're dequeueing a reusable cell, and you're getting the same cell.
Make sure to set your .setTarget() call for your buttons in your tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) data source every time the cell is dequeued. It would help if you shared how you're handling dequeuing to see if this is your issue.

Related

UIButton behavior changes if collectionView moveItemAt is overridden

I have a collection view controller. One of collection view's cells contains a button with Touch Down and Touch Up Inside.
Strictly speaking, the button is in the view of view controller which is a subview of the collection view cell.
When the button is pressed the Touch Down is fired and when the button is released the Touch Up Inside is fired. Until the button is not released the button is grayed and the Touch Up Inside is not fired.
This is exactly the behaviour I need.
Now, I have implemented these two methods to support reordering collection view's cells:
func collectionView(_ collectionView: UICollectionView, canMoveItemAt indexPath: IndexPath) -> Bool
func collectionView(_ collectionView: UICollectionView, moveItemAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath)
If the second method is implemented (both if canMoveItemAt returns true or false), the button behavior changes:
as soon as the button is pressed, fires the Touch Down event and immediately after that, it also fires the Touch Up Inside event.
the button is grayed when pressed and immediately gets back to its normal state like it has been released
when the button is released, nothing happens
My suspect is that events propagate from button to the collection view controller, but I have no idea how to prevent it.
Can anyone help me?
Tks
You are right, but if you stop it, you stop reordering as well. Basically you need to choose what do you need: button to be pressed or cell to be dragged. Perhaps you can achive expected behaviour utilising Collection cell capabilities, instead of button. You can easily change button states, if you need button to represent that cell is being dragged.

How do I call a specific TableViewCell

The first cell in this TableViewController is suppose to alert the user when their status is liked or favorited. I need to create a function so when a button is tapped, it will call this table view cell and notify them who liked their photo. I am just not sure how to call this specific table view cell. Can anybody help me out? I have searched SO and Apples Swift Documentation with no luck.
In your didSelectRowAtIndexPath tableview delegate method you can get the index path (row position) of the cell they tapped on and then if you've got an array of data (used to populate the tableview in the first place) you know where to look to find out which notification/activity it is:
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let selectedItem = items.objectAtIndex(indexPath.row) as String
}
You can also get the cell by adding this inside the method:
let cell = tableView.cellForRowAtIndexPath(indexPath)
You can get the reference to the cell with cellForRowAtIndexPath method of UITableView.

Find Out Which Section Button Belongs To In UITableView When Clicked Inside Cell

I am trying to change the value of an element of an array depending which section a button is clicked in. For example say I have this array numbers = [0,0,0,0,0] and I want to change the first element to 5. I insert 5 into the cell of the first section and click done in that same section and the array will now read [5,0,0,0,0]. Is there a way to know which section the button belongs to?
Right now I have two separate classes. One for the custom cell and one for the tableview. Both of the have an outlet to the button. When the button is clicked the custom cell class changes a temporary global number to the inserted number. And inside the table class I want the button action to take that global number and insert in into the element that is the same number as the section the button belongs to. Except I don't know how to find out which section it belongs to.
Can anyone help me out with this? I'm writing in Swift btw.
If you only need the section (not the section and row) of the index path of the cell containing the tapped button, you could tag the button with the section number (Int) when you configure the table view cell:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCellWithIdentifier("MyIdentifier", forIndexPath:indexPath) as! MyCustomTableViewCell
cell.myCustomButton.tag = indexPath.section
// Remove all existing targets (in case cell is being recycled)
cell.myCustomButton.removeTarget(nil, action: nil, forControlEvents: .AllEvents)
// Add target
cell.myCustomButton.addTarget(self, action:"buttonAction:", forControlEvents:.TouchUpInside)
return cell
}
func buttonAction(sender:AnyObject)
{
if let button = sender as UIButton{
println("Tapped Button in section: \(button.tag)")
}
}
If you need both the section AND the row, you're better off storing the whole index path. For that, you can either use a custom UIButton subclass with a property of type NSIndexPath, or store it in the table view cell.
But the second solution is a bit messy since you have to access the table cell (and then, the index path) from the button by using superview, etc., and this relies on the table cell's subview structure. I'm not sure if the parent view of your button is the table cell itself, or its "content view" (I'm a bit rusty right now...)
If you want to find which cell has been 'clicked' you could use the UITableViewDelegate method.
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
}

Dynamic UITableView is not calling the delegate

I need to add a table view in a specific are of my screen which is inside another UIView. When the user press a button the table view is created and displayed perfectly fine. However I need to know the user selection so I create it in the following way:
self.dynamicTableView = UITableView(frame: self.viewForTableView.bounds)
self.dynamicTableView?.dataSource = self
self.dynamicTableView?.delegate = self
self.messageZone.addSubview(self.dynamicTableView!)
self.dynamicTableView?.reloadData()
The data sources methods are being called but the delegate is not, so the following println is not working
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
println("Hello")
}
As additional information I'm using a custom table view cell
UPDATE: I just discover that if I implement shouldHighlightRowAtIndexPath sometimes if I do a long press it works, like if I keep the cell pressed for about four seconds, but not always, just some times. Can it be any view that is behind the table view what is causing this weird behaviour?

Modifying the text in a static UITableView cell?

I'm using a "Static Cells" table view created in my storyboard file. However I'd like to update the text on one of these cells when a setting is changed.
I'm pushing a view controller which updates the setting. I'm trying to use a callback to change the cell's text when it's popped off the stack, but by that point the cell has apparently been recycled or reused, so the old object is off screen and no longer used in the table view.
Is there a way I can update this text, and make it permanent (so that when the cell is scrolled off screen and comes back, the new value still appears)?
Assuming your table view hierarchy is along the lines of:
Table View (static cells)
- Table View Section
- Table View Cell
- UILabel (with the text property you want to modify)
Declare an IBOutlet UILabel in your code, and wire it up in the storyboard's UILabel in the table view hierarchy above.
In your callback method, set your UILabel's text property as you see fit.
You can store text that you want to change as a property and use it in:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = super.tableView(tableView, cellForRowAtIndexPath: indexPath)
switch (indexPath.section, indexPath.row) {
case (0, 3):
cell.textLabel?.text = yourProperty
default: break
}
return cell
}

Resources