Segmented control in tableCell - ios

I have a problem with segmented control in table cell. No action of Segmented control
segmentedFilter.addTarget(self, action: #selector(ProductListFilterCell.filterSelected), forControlEvents: .AllEvents)
Target function:
func filterSelected() {
if let order = ProductListViewModel.OrderBy(rawValue: segmentedFilter.selectedSegmentIndex), let change = orderChanged{
change(order)
}
}
Is it possible to have segmented control in table cell ?

It is incorrect to call addTarget in prepareForReuse, because this method is called when the cell is no longer needed. Only reused cells would have a selector on them.
The second problem is the target: you are passing self, which is the data source for the table, but the selector refers to the cell. If you bring up a reused cell by scrolling up and down several times, your control would trigger the event, and the app would crash with unknown selector message.
You can fix this by moving the method into the data source class, adding target in cellForRowAtIndexPath, and removing the target in prepareForReuse.
segmentedFilter.addTarget(self, action: #selector(ProductListDataSource.filterSelected), forControlEvents: .AllEvents)
// ^^^^^^^^^^^^^^^^^^^^^^

Related

Can't press the button in UITableViewCell after iOS 15 update

I have a UITableView that rapidly update the data and there is a button in the UITableViewCell. From iOS 11 to 14, it works perfectly but after the iOS15 update, the button is broken.
It seems to be untouchable while the cell is updating. So, I can't touch the button
It need to touch on it a lot of times to make the button action fired
When it fired, some time is fire as another cell context. For example: I press the button on cell 1 it should send the sender from cell 1 to the responder but it send the sender from cell 2 instead
The button was embedded as
cell.contentView.isUserInteractionEnabled = true
cell.button.addTarget(self, action: #selector(self.doSomething(sender:)), for: .touchUpInside)
Anyone has some suggestion for me? Thank you
UPDATE
I found the solution is use reconfigure instead of reloadData for UITableView
let indexPaths = tableView.indexPathsForVisibleRows!
if !indexPaths.isEmpty {
tableView.reconfigureRows(at: indexPaths)
}
cell.contentView.isUserInteractionEnabled = true
Remove this line in your code.

Create action for a button inside collection view

I have created a UICollection View inside a storyboard, I have created a button inside the cell, whenever I tap on the button I should filter the data as per my condition, so each and every buttons inside the cell will have different conditions, can anyone help me out with this issue ?? Iam using xcode 9 and swift 4.
Use addTarget of your button inside cellForItemAt:indexPath datasource and add a selector where action of the button will be defined. Add this button's tag, (add it same as your indexPath.row, that you can use to differentiate your button from collectionview)
cell.yourButton.addTarget(self, action: #selector(yourButtonTapped), for: .touchUpInside)
cell.yourButton.tag = indexPath.row
Now add the action of that button and inside that perform any action you need.
#IBAction func yourButtonTapped(_ sender: UIButton) {
//perform action
}
Create a custom UICollectionViewCell type. Wire up an IBAction to the cell.
Create a protocol that lets the cell notify the collection view that the user tapped a button. Have the action pass the tap to the delegate.
In your cellForItemAt() method, set the view controller as the delegate.
Now in your view controller handle the tap as desired.
Try this for Objective c
Add below code at cellForRowAtIndexPath
cell.btnOk.tag = indexPath.row ;
[cell.btnOk addTarget:self action:#selector(OkBtnAction:) forControlEvents:UIControlEventTouchUpInside] ;
Than add the action of that button
-(IBAction)OkBtnAction:(id)sender
{
UIButton* btn=(UIButton*)sender;
NSLog(#"row: %ld",(long)btn.tag);
}

How to callback a function in tableView's Class from tableViewCell's Class

I'm having a TableView. In that tableView, I custom it's cells
like this
In this cell I have 2 part. An Image and an TextField.
It's look like facebook's post status. When I click to Image, I want to open a new ViewController and the same for TextField
But I have a problem that I can't call segue from my cell's class file.
Are there any way that I can call a function in TableViewController's class from TableViewCell's class ?
I know that I can use delegate but I don't like this way a lot, because if I do this way I have to set a lot of delegate in my project.
Are there any better way to present a new ViewController directly from TableViewCell's class
Using a delegate is a very good way to solve your problem.
If you don't like that solution then you could design a table view cell that has a closure property set by the view controller, and invokes that closure when the button is pressed.
EDIT:
Another alternative is to leave the button action empty in your custom cell, but still connect up outlets to the buttons.
Then in your cellForRow(at:) method, install an IBAction that has your view controller as the target. (Credit to #SoanSani, who's answer is below)
In that IBAction method, you can use the coordinates of the button to figure out the indexPath of the cell hat contains the button that was tapped.
I've created an extension to UITableView that lets you figure out the cell that contains any view. The code is below:
import UIKit
public extension UITableView {
/**
This method returns the indexPath of the cell that contains the specified view
- Parameter view: The view to find.
- Returns: The indexPath of the cell containing the view, or nil if it can't be found
*/
func indexPathForView(_ view: UIView) -> IndexPath? {
let origin = view.bounds.origin
let viewOrigin = self.convert(origin, from: view)
let indexPath = self.indexPathForRow(at: viewOrigin)
return indexPath
}
}
You can use delegates, but if you dont want to use delegates
while setting up the cell add target to your button tableViewController class and then you can receive all events in tableview class rather than cell class.
But this would require to add tags which you can use to differentiate which button in cell was clicked
Objective C Code
[OkBtn addTarget:self action:#selector(okButtonTapped:) forControlEvents:UIControlEventTouchUpInside];
Swift Code
OkBtn.addTarget(self, action: #selector(ViewController.okButtonTapped), for: .TouchUpInside)

Select a cell by UIButton - CollectionViewCell - Swift

I'm using collectionView, and I customized the collectionViewCell in a separate class with type (collectionViewCell). I want to perform an animation when user clicks on a cell. So, I created a UIButton in collectionViewCell and I customized it to cover the whole cell.
button = UIButton(frame: self.frame)
button.addTarget(self, action: "scaleToSmall", forControlEvents: .TouchDown)
self.addSubview(button)
Right now, the animation works perfectly, but the issue is I lost the ability select the cell, and the function didSelectItemAtIndexPath does not call anymore
I found out how to get the indexPath of the cell that has clicked,
But how can I call didSelectItemAtIndexPath again and tell it this cell is selected in order to perform the next action (segue to another ViewController) ???
Thanks in advance!!
You said that you created a button that covers the whole cell, if I have that right. Because of that, didSelectRowAtIndexPath won't do anything because that button is covering the whole cell. Take the Twitter app, for example. You can tap on the cell to open the tweet or you can tap on the user's profile image to open their profile. In this case, it's like you have the profile picture button covering the whole cell. Maybe you can set the animation in didSelectRowAtIndexPath or make the button smaller.
Hope this helps!

change font in UITapGestureRecognizer

I have a UIView, in which I have one UILabel. I would like to change the UILabel.Font to a custom UIFont when the UIView is tapped (This enlarges the tappable area instead of using a UIButton).
To add the UITapGestureRecognizer, I use the following code:
var gestureRecognizer = new UITapGestureRecognizer ((item) => {
(item.View.Subviews[0] as UILabel).Font = Constants_iOS.FONT_OS_SMALL_LABEL_SEMIBOLD;
});
view.AddGestureRecognizer (gestureRecognizer);
The font change gets executed, and stepping through the code shows the font changing. But it does not update in the UI, and all subsequent executions of the function also start with the Font being the old one.
What is going wrong?
Add tap selector method.
let tap = UITapGestureRecognizer(target: self, action: Selector("handleTap:"))
tap.delegate = self
view.addGestureRecognizer(tap)
func handleTap(sender:UIGestureRecognizer){
//change your font here
}
Please note that a UITableview header gets redrawn each time it gets tapped. So your font change will not persist.

Resources