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

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)

Related

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 can I get a Table View to register taps when each cell has an Image View covering it?

I've been trying to create table view cells each with a UIImageView serving as a background for them. However, when I tap on each cell the table view will not register the click and will not transition to the view controller I have hooked up, even while I'm using the didSelectRowAtIndexPath function.
I realize it's probably an issue with the ImageView obstructing the table views ability to register the cell tap. The cells will transition however when I drag my finger/mouse on it from left to right, just not on taps. I tried to use a Tap Gesture Recognizer on the Image View however it only worked for the cell at the very top and not all of them. How do I tackle this issue?
Here is an image of the table view cells so you have an idea of what I'm working with: http://imgur.com/a/Ku4uD. Thank you!
If you uncheck User Interaction Enabled on your Image View, the problem should be solved. When running into a problem always check the user interaction of the most child view and work your way up.
One trick I have also learned is to create a subclass of a child and override touchesShouldCancel like so:
override func touchesShouldCancel(in view: UIView) -> Bool {
print("touchesShouldCancel")
//Run extra code that you want when the user selects this view
//then still retrieve the tap by its parent.
return false
}
I am unsure of exactly what your problem is, but I would delete whatever segue that you have, add a new one by dragging from the yellow circle on the left side of the center portion of the top of your tableView ViewController inside the storyboard, to the viewController that you desire it to segue to. Give the segue an appropriate identifier, and then inside your tableView class under tableView didSelectRow add performSegue(withIdentifier: "ChosenIdentifier", sender: indexPath)
Then in prepare forSegue add in:
if let vc = sender.destination as? TheViewControllerYouAreSegueingTo {
if let indexPath = sender as? IndexPath {
vc.variableIdentifyingWhatCellWasClicked = indexPath.row
}
}
with whatever adjustment is needed to meet your specific needs.

Custom UITableViewCell button click

In a UIViewController there is a UITableView which consists custom UITableViewCell with a UIButton.
When the user clicks the button (in the custom UITableViewCell), I want to display a message in the hosting UIViewController - what is the right way to achieve that? How should I notify the UIViewController that the button was clicked?
You should use delegation to tell the UIViewController that something happened in the cell.
I'm not exactly sure what kind of message you are referring to but if you mean a you want to show a popup just create a UIAlertView and show it when the button is clicked in the cell.
However, if you mean change a UIlabel text or whatever as a message on the ViewController you can always pass whatever you need to change into the TableView and Cell or the UIViewController itself into it.
I usually create a method on the custom cells class and pass it whatever I need into the custom TableView's constructor. Then in the TableView's GetCell() method pass whatever I need to change into that method I created on the cell and save it as a variable on the cell.
If you've initiated your UITableViewCell, and added a button to the cell, you can use a Delegate when the button is clicked, something like this:
UIButton button = new UIButton (cell.Bounds.X, cell.Bounds.y, cell.Bounds.Width, cell.Bounds.Height);
button.TouchUpInside += (object sender, EventArgs e) =>
{
label.text = "Blablabla";
};
Where the label is, is up to you. I hope this helps, good luck!

Handle button click inside UITableViewCell

I can't seem to handle a button click properly inside a custom UITableViewCell. It's a cell that contains a label and a button. I have the following code:
var cell = tableView.DequeueReusableCell (cellKey) as ApptHistoryCell;
if (cell == null)
{
cell = _container.Cell;
cell.SelectionStyle = UITableViewCellSelectionStyle.None;
}
if (InfoClicked != null)
{
cell.ActionButton.TouchUpInside += InfoClicked;
}
InfoClicked is an event handler passed on in loop on cell creation. When the cell is re-used, this causes a null reference exception, because (I think) TouchUpInside is trying to call 2 handlers. Old one and the new one, which causes a crash. If I put the event handler inside cell == null if block, then the wrong action is shown.
How can I handle the click properly?
Thanks!
The way I handle buttons inside custom cells:
I define an IBAction that I connect to a UIButton event inside the custom cell
I define a delegate and a delegate method for the cell to handle the button action
The IBAction calls that delegate method
When defining your cells in cellAtRow... I set the tableViewController to be the delegate. cell.delegate=self;
I do whatever action I would like to do inside that delegate method in the tableViewController
Makes sense?
you should create your cell from a xib file, which already connects the buttons to the owner's targets (the view controller).
In your custom cell just locate your button at IB and make connection with the property.
Now, in the controller at cellForRowAtIndexPath, what you need, just tag that button, say:
(MyCustomCell*)cell.myButton = indexPath.row;
Now, after that just set the click event like that:-
[(MyCustomCell*)cell.myButton addTarget:self action:#selector(NeedFunctionToCall:) forControlEvents:UIControlEventTouchUpInside];
Now, at same view controller, implement that required method, like that:
-(void)NeedFunctionToCall:(id)sender
{
NSLog("Got the event :-> %d, from the cell/button",[sender tag]);
}

Custom UITableViewCell Button and RowSelected (iOS/Monotouch)

I have a 'Load More' UIButton inside a custom UITableViewCell. My table also uses a Delegate. I want to reload the table data when this button is clicked. I have noticed that when I click the button, nothing happens. But when I click on the area around the button i.e. the actual Cell, the Delegate gets the RowSelected event.
I tried using SetSelected(true,false); from the button's touch up inside event to see if it would fire the RowSelected event for the delegate, but it didn't.
Can anyone explain me how I can make a button click for a Custom Table cell fire the actual Row Selected event? If this isn't a viable option, is there a better way to 'Load more data' other than placing the button inside a custom table view cell?
Thanks!
UPDATE:
I do use ContentView.AddSubView as shown in the code below. Please note I'm using Monotouch, but the logic is the same:
public LoadMoreCell (string reuseCellIdentifier)
:base(UITableViewCellStyle.Default, reuseCellIdentifier)
{
SelectionStyle = UITableViewCellSelectionStyle.None;
_btnLoadMore = UIButton.FromType(UIButtonType.RoundedRect);
_btnLoadMore.Frame = new RectangleF(10,5,300,30);
_btnLoadMore.SetTitle("Load More", UIControlState.Normal);
_btnLoadMore.UserInteractionEnabled = true;
ContentView.AddSubview(_btnLoadMore);
}
I have a TableDelegate that has a RowSelected method where I reload the data...however, the RowSelected only gets fired when I click the actual row.
I think you might have added the uibutton as
[self addSubView:yourButton];
instead use :-
[self.contentView addSubview:yourButton];
and all the other controls of your custom cell.
Do this in the initializer of your custom cell :-
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {}
make a custom UITableViewDataSource for your table
and when you hit the button 'Load more', call a method of this datasource to add other data to the list of the datasource, add this datasource to your table and make sure to reload the data of the table
this.tblData.ReloadData ();

Resources