i created a .xib with my custom cell that I'm using on one of my tableviewcontroller in my storyboard.
In the storyboard, I linked the current tableview with another tableview with a push segue. (when the user click on one of the cell, he has a new view).
The problem is, I don't understand, how to "link" this segue, with my CUSTOM cell ?
I'm loading my custom cell like that :
static NSString *simpleTableIdentifier = #"cellCustom";
cellCustomView *cell = (cellCustomView *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"cellCustom" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
and when I try to implement the method :
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
NSLog(#"test");
}
I've nothing, because according me, I missed something to do with my custom cell, and the segue of my storyboard, but I don't understand how it works :/
thx,
Did you try this?
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[self performSegueWithIdentifier:#"MySegue"
sender:self];
}
This method belong in whichever class contains the tableView. Make sure that the tableView's delegate is equal to self in that class. If you're using a storyboard, control-drag this view to whichever view you want to segue to. Click on that segue, and change its identifier to "MySegue" or whatever you want, as long as its the same in your code.
You can try the following approach
Control + Drag from your cell to next view controller to setup a segue called "showDetail", that you want to show on clicking tableview cell.
and in your view controller
if you have nsarray such as
NSArray *names = #[#"Apple", #"Google", #"Microsoft"];
and you want to pass the array value based on the selected table row cell index, you can as follows
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"showDetail"])
{
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
NSString *name = _names[indexPath.row];
// For explanation sake, I am assuming name as property defined
// in your destination view controller
[[segue destinationViewController] setName:name];
}
}
Related
I have a controller with a listview that contain a custom cell.
I have created a modal segue from the cell to the next controller and I gave a name to this segue but when I click on the cell, prepareForSegue isn't called.
I could use the didSelectRowAtIndexPath and performSegueWithIdentifier but I have to send data to the next controller from the cell I've clicked on.
Any idea why the prepareForSegue isn't called? Or how to send data to the controller with another method?
You can get the cell data in didSelectRowAtIndexPath by getting the cell from the index of customCell that you clicked, and after you can performSegueWithIdentifier.
So let's make this easier:
Under your didSelectRowAtIndexPath method, add this line to get the properties of your customCell
YourCustomCell *customCell = (YourCustomCell *)[self.tableView cellForRowAtIndexPath:indexPath];
So now if you have something stored under your customCell you can access it from customCell instance.
After you managed to store or manipulate your data from customCell you do the performSegueWithIndenfier:
[self performSegueWithIdentifier:#"yourSegueID" sender:self];
Hope this helps
When you connect a segue from a cell to another view controller, unless it's a static table view, you'll have to trigger performSegueWithIdentifier from the didSelectRowAtIndexPath
After you execute performSegueWithIdentifier, prepareForSegue would be called.
In prepareForSegue, you can set up your destination view controller, which you can access via segue.destinationViewController
Like so:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
[super prepareForSegue:sender sender:sender];
if ([segue.identifier isEqualToString:#"YOUR_SEGUE_NAME_HERE"]) {
UIViewController *destinationViewController = segue.destinationViewController;
}
}
Or if you need to set things up in the didSelectRowAtIndexPath , you could do (iOS7+ only)
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[self performSegueWithIdentifier:#"YOUR_SEGUE_NAME_HERE" sender:self];
UIViewController *destinationViewController = [self.transitionCoordinator viewControllerForKey:UITransitionContextToViewControllerKey];
}
Update:
Turns out #rdelmar is correct, it does work with dynamic cells.
All you have to do then is
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
[super prepareForSegue:sender sender:sender];
if ([segue.identifier isEqualToString:#"YOUR_SEGUE_NAME_HERE"]) {
NSIndexPath *selectedIndexPath = [self.tableView indexPathForCell:sender];
}
}
And you have the index path of the cell that was tapped. Then you can use that to query your datasource and find the object that was used to populate that cell.
I have a table view with cells created with:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = #"GalleryCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIdentifier];
}
NSMutableArray *gallery = [gallerys objectAtIndex:indexPath.row];
cell.textLabel.text = [gallery objectAtIndex:1];
return cell;
}
What I need to be able to do is within the didSelectRowAtIndexPath, fire a segue to launch another view, this will also send some information across using the prepareForSegue method.
This issue is I am not sure how to go about creating the segue to be used in this instance as within the storyboard I have nothing to attach it to (no buttons etc) and the cells are created within the code, is it possible to also create the segue in the code? Or is there another method to this?
Okay, you can attach it to your table view controller, it is not necessary to attach it to a button. Just go to the storyboard and do the following:
Right click on the VC that you would like to push.
Under Presenting Segues in the menu click and hold 'push' and drag it to your table view controller.
Choose manual when the dialog shows above your table view controller.
Select the segue after it appears and go to its attribute inspector.
Choose a name for the segue.
Call performSegue
simply drag a segue from your table to destination Controller and give a name for that.
And in didSelectRowAtIndexPath call
[self performSegueWithIdentifier:#"MySegue" sender:self];
then following method will get called
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// here you can pass any value to new ViewController;
if ([segue.identifier isEqualToString:#"MySegue"]) {
YourNewViewController *VC = segue.destinationViewController;
VC.data = yourData;
}
}
Push your view controller
[self performSegueWithIdentifier:#"yourSegueID" sender:self];
You can send the information as below
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"yourSegueID"]) {
YourViewController *yourVC = segue.destinationViewController;
yourVC.information = myInformation;
}
}
I have a simple table view that can segue to an update-view-contoller to edit that row when the user taps on a row. Issue: I would like to segue to the update-view-contoller when the table view is in "edit-mode", otherwise nothing should happen.
I am using Storyboard to create the segue linking the prototype cell to the update-view-controller.
Any idea on how to make the segue work only if the table view is in "edit-mode"?
Here is my prepare for segue code that is invoked when the user taps on a row from the table view contoller. My segue has an identerfied called "ShowUpdate":
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([[segue identifier] isEqualToString:#"ShowUpdate"]) {
UpdateViewController *updateviewcontroller = [segue destinationViewController];
NSIndexPath *myIndexPath = [self.tableView indexPathForSelectedRow];
int row = [myIndexPath row];
NSString *selectedRow = [NSString stringWithFormat:#"%d", row];
updateviewcontroller.DetailModal = #[_Title[row], _Description[row], selectedRow];
}
}
Thanks for any help
How about a simple if check for isEditing property of the tableView?
#property(nonatomic, getter=isEditing) BOOL editing
Instead of making a segue from a prototype cell, I would drag it from the ViewController itself, and then check the above property in the didSelectRowAtIndexPath: delegate method and perform the segue in code from there.
Plus, you would need to set allowSelectionDuringEditing property somewhere in viewDidLoad or so.
self.tableView.allowsSelectionDuringEditing = YES;
Code:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (self.tableView.isEditing) {
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
[self performSegueWithIdentifier:#"ShowUpdate" sender:cell];
}
}
Segue construction:
I've a tableView and I'd like to switch to another view by clicking a button in the center of the cell. I use dynamic cells.
So, I want to switch to a view (in a navigation controller) with the click of a button in a cell, how can I do it in prepareForSegue? I can get the index of the cell, and then to do this step by clicking the disclosure, but when I click on my button located in the center of the cell, the indexpath does not exist. Here the code:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
UIViewController *destination = segue.destinationViewController;
if ([destination respondsToSelector:#selector(setDelegate:)]) {
[destination setValue:self forKey:#"delegate"];
}
if ([destination respondsToSelector:#selector(setSelection:)]) {
NSIndexPath *indexPath = [self.tableFeed indexPathForCell:sender];
NSString *idUser = [self.arrIDUser objectAtIndex:indexPath.row];
NSLog(#"%#",idUser);
NSString *pattern = [self.arrPattern objectAtIndex:indexPath.row];
NSMutableDictionary *selection = [[NSMutableDictionary alloc] initWithObjectsAndKeys:idUser,#"idUser", pattern, #"pattern", nil];
[destination setValue:selection forKey:#"selection"];
}
}
First you need to grab the cell, then its superview i.e UITableViewCellContentView, then the table that has this cell. Here is the code.
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
NSLog(#"prepare for segue");
//sender is UIRoundRectButton
UITableViewCell *cell = (UITableViewCell*) [[sender superview] superview];
UITableView *table = (UITableView*)[[[sender superview] superview] superview];
NSIndexPath *indexPath = [table indexPathForCell:cell];
NSLog(#"%i %i",indexPath.section,indexPath.row);
}
This would give you the index path for the cell in which the button was tapped.
You can get the indexPath by going to the superview of the button to get the content view and then to the superview of the content view to get the cell. But this is kind of ugly.
A better approach can be found in iOS Recipes where they transform the origin of the button to the table view via convertPoint:toView: and then call indexPathForRowAtPoint: to get the indexPath.
you have to create button in cellForRowAtIndexPath delegate method and assign tag to taht button. Based on that you will get that which row has selected.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
selectedDealIndex = indexPath.row; //here you will get selected index
[self performSegueWithIdentifier:#"your_seguename" sender:self]; //here you have to pass your seguename which you have written in xib[in properywindow]
}
First I need to clarify that when I don't use a detail disclosure button and just the disclosure indicator everything works perfectly.
After quite a research I am struggling with how to pass the correct data from one tableview to another, when the detail disclosure button is tapped. I am using core data to store my data and I have created the appropriate segue (Item Details Segue) from the master UITableViewController (SGProfileTVC) to the detail one SGItemDetailsTVC.
Here is my implementation of prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if([segue.identifier isEqualToString:#"Add Item Segue"])
{
NSLog(#"Setting SGProfileTVC as a delegate of SGAddItemTVC");
SGAddItemTVC *sgAddItemTVC = segue.destinationViewController;
sgAddItemTVC.delegate = self;
sgAddItemTVC.managedObjectContext = self.managedObjectContext;
} else if([segue.identifier isEqualToString:#"Item Details Segue"])
{
NSLog(#"Setting SGProfileTVC as a delegate of SGItemDetailTVC");
SGItemDetailTVC *sgItemDetailTVC = segue.destinationViewController;
sgItemDetailTVC.delegate = self;
sgItemDetailTVC.managedObjectContext = self.managedObjectContext;
// Store selected item in selectedItem property
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
self.selectedItem = [self.fetchedResultsController objectAtIndexPath:indexPath];
NSLog(#"Passing the selected item (%#) to SGItemDetailTVC", self.selectedItem.name);
sgItemDetailTVC.item = self.selectedItem;
} else {
NSLog(#"Unidentified Segue");
}
}
I have also implemented the tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath method
- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath
{
[self performSegueWithIdentifier:#"Item Details Segue" sender:[self.tableView indexPathForSelectedRow]];
}
What is happening is that it segues normally, however when the new tableview loads it doesn't contain any data.
Any suggestions would be very much appreciated!!
Thank you!
Does your new Table View have a Fetched Results Controller? It should have one as the fetched results controller manages automatically the data display (e.g. reloads) of your table view.
I guess that when you use an accessory button, the cell isn't selected.
Instead of getting the indexPath with indexPathForSelectedRow, try to get the cell from the sender (which should be the cell itself or the accessory button, I can't test it right now). Once you have the cell, use indexPathForCell: to get its indexPath
Imotep has the correct answer. The code looks like this:
UITableViewCell *cell = (UITableViewCell*)sender;
NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];