Hi I have a storyboard and am able to show a detail view when clicking on a table cell. I want to add extra functionality so that depending on what cell I click I show a different view controller. I tried dragging two segues from the same cell but it doesn't allow it.
My thinking was that I would have two segue's from the cell each pointing to a different view and then invoke the desired segue:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSInteger row = indexPath.row;
NSLog(#"Selected Item :-) %#",[NSString stringWithFormat:#"%#",[myData objectAtIndex:row]]);
if(row %2 ==0){
NSLog(#"Even");
[self performSegueWithIdentifier:#"ShowSecondIndex" sender:self];
}else{
[self performSegueWithIdentifier:#"ShowSelectedMovie" sender:self];
NSLog(#"Odd");
}
}
I would then handle the segue in prepareForSegue
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
NSLog(#"Prepare For Segue ID:%#",[segue identifier]);
if([[segue identifier] isEqualToString:#"ShowSelectedMovie"]){
Tab2_ItemViewController *vc = [segue destinationViewController];
NSInteger selectedIndex = [[self.tableView indexPathForSelectedRow] row];
NSLog(#"Selected Index: %d",selectedIndex);
[vc setSelectedItem: [NSString stringWithFormat:#"%#",[myData objectAtIndex:selectedIndex]]];
NSLog(#"String Value: %#",[NSString stringWithFormat:#"%#",[myData objectAtIndex:selectedIndex]]);
[vc setSelectedIndex:selectedIndex];
}else if([[segue identifier] isEqualToString:#"ShowSecondIndex"]){
NSLog(#"Viewing Second Index");
}
}
However it never shows the second view. Is this because its not possible to have two segues from a single table cell. I also tried dragging both segue's from the controller to each destination rather than one from the cell and one from the controller but sill no luck???
Don't try to hook up the Segues to a tableviewcell in this case. Hook them up to the View Controller itself.
Don't try to create multiple segues from a TableCell to other view controllers, you want to ctrl+drag from the view controller icon below the view controller in the storyboard interface to the viewcontrollers you want to segue to. Then it will allow you to set up multiple segues.
and then to actually make the segues work, you need to add identifiers to the segues themselves, which you can do by clicking on them and then giving it a name in the property inspector:
then, for the example of TableCells, in your UITableViewDelegate, in
-tableView:didSelectRowAtIndexPath:
you can use
- (void)performSegueWithIdentifier:(NSString *)identifier sender:(id)sender
to manually start a segue depending on your own logic of what segue should be chosen.
Here's a sample code from my demo project:
- (void)tableView:(UITableView *)tableView
didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *segueName = nil;
if (type == kCore) {
segueName = #"segue1";
} else if (type == kStdlib) {
segueName = #"segue2";
}
[self performSegueWithIdentifier: segueName sender: self];
}
type is a property of view controller, which determines which segue should be performed.
As the above answer said, the key is to create segue by linking two view controllers.
In swift 3.1, with a segment control of two states
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
var segue: String!
if selectedSegment == 0 {
segue = "segue1"
} else {
segue = "segue2"
}
self.performSegue(withIdentifier: segue, sender: self)
}
Related
I have a problem.
I have a ViewController embed in navigationController.
And use the storyBoard to add the tableView in this viewController.
then,I add the segue.
Finally,I click the cell that the next viewController show twice.
I don't know how to fix it.
Thanks!
This is my code:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if(indexPath.row == 2){
[self performSegueWithIdentifier:#"showAdd" sender:self];
}
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if ([segue.identifier isEqualToString:#"showAdd"]) {
AddCommentViewController *AddCommentVC = segue.destinationViewController;
AddCommentVC.CommentString = _DetailString;
}
}
You have to add the segue between both the UIViewController, not with the cell and UIViewController, as you have connected that segue on click of cell and you are calling the segue manually also that's why it is showing twice.
Do one thing, remove the segue and connect it between UIViewControllers then it will called only once.
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 have a table. When I click on the cell segue should be performed. I try to use prepareForSegue and performSegueWithIdentifier, but without any result.
My code:
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if([segue.identifier isEqualToString:#"OpenB"]){
OpenBViewController *controller = (OpenBViewController *)segue.destinationViewController;
controller.address = self.selectedCellText;
[self performSegueWithIdentifier:#"OpenB" sender:self];
}
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
self.selectedCellText = [[[tableView cellForRowAtIndexPath:indexPath] textLabel] text];
[self performSegueWithIdentifier:#"OpenB" sender:self];
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
First of all, you shouldn't call [self performSegueWithIdentifier:#"OpenB" sender:self]; inside of -prepareForSegue: method because -prepareForSegue is called when segue is about to be performed.
Second, check that you have your segue setup correctly. Make sure you have provided the same identifier to the segue in the storyboard that you are using with -performSegueWithIdentifier:
Your code should be as follows:
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if([segue.identifier isEqualToString:#"OpenB"]){
OpenBViewController *controller = (OpenBViewController *)segue.destinationViewController;
controller.address = self.selectedCellText;
}
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
self.selectedCellText = [[[tableView cellForRowAtIndexPath:indexPath] textLabel] text];
[self performSegueWithIdentifier:#"OpenB" sender:self];
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
And keep in mind to setup a segue with identifier OpenB in storyboard.
I know this is old, but just leaving this here in case it happens to someone else.
Also, all code is in Swift 3, because my knowledge of Objective C syntax is next to nil.
The problem was most likely that the didSelectRow() method gets called after the segue was pushed. So when the prepare(ForSegue) one gets called, the selectedTextCell variable has not been properly initialized.
If you're connecting from the cell to the next ViewController via a segue created in the Interface Builder, you don't need to use didSelectRow() and probably you shouldn't, because the segue is likely to be always pushed before didSelectRow().
In that case, all you need to do is retrieve the information from the cell in the prepare() method.
The signature is:
func prepare(for segue: UIStoryboardSegue, sender: Any?)
The sender is whichever object triggers the segue. In this case, the cell that was selected. So, in prepare(), you would write something like this:
let myCell = sender as! UITableViewCell
controller.address = myCell.textLabel.text
If you need to access the row, for example, it would be:
controller.idx = self.tableView.indexPath(for: sender as! UITableViewCell)?.row
Of course, UITableViewCell can be replaced by any custom Cell class you may have.
I have 3 segues to 3 different views. 2 are implemented with no problem, it is when the third is created that the problems occur.
I have the following didSelectRowAtIndexPath method:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
NSLog(#" ---------- did select row");
if(indexPath.section == 0){
if(indexPath.row == [self.data count]-1){
//prior to adding this, everything works
[self performSegueWithIdentifier:#"MoreComments" sender:self];
}else{
[self performSegueWithIdentifier:#"FriendView" sender:friend];
}
}else if(indexPath.section == 1){
if(indexPath.row == [self.data2 count]-1){
[self performSegueWithIdentifier:#"MorePosts" sender:self];
}else{
[self performSegueWithIdentifier:#"FriendView" sender:friend];
}
}
}
I have the following prepareForSeque method:
-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if([segue.identifier isEqualToString:#"MorePosts"]){
MorePostsViewController *mfamvc = segue.destinationViewController;
mfamvc.data = self.data;
}else if([segue.identifier isEqualToString:#"FriendView"]){
FriendViewController *fvc = segue.destinationViewController;
fvc.friend = friend;
}else if([segue.identifier isEqualToString:#"MoreComments"]){
MoreCommentsViewController *mcvc = segue.destinationViewController;
mcvc.data = self.data2;
}
}
Before control dragging from my cell to the last view I can see that my program hits didselectrow and then prepareforseque. This makes all the view navigation work perfect.
As soon as I control drag from my cell to the MoreCommentsViewController I start to see the error:
nested push animation can result in corrupted navigation bar
Finishing up a navigation transition in an unexpected state. Navigation Bar subview tree might get corrupted.
I notice that now also prepareforseque is being called twice, with prepareforseque being called first, then didselectrow, then prepareforsegue again.
What am I doing wrong to conditionally go to these different views?
You should use either didSelectRowAtIndexPath or segues from cell, but not both. If you want your didSelectRowAtIndexPath to invoke segues, those segues should not be from the cell to the next scene, but rather from the view controller icon in the bar above the scene:
You can now select this new segue, go to the "attributes inspector" (option+command+4), and supply a storyboard identifier which you can reference in your code when you call performSegueWithIdentifier.
The reason is you can't drag from a tableview cell to multiple views. As #rdelmar mentioned this is wrong. You should drag from the destination to the source view and then handle manually the way I did above.
Also can be found here: Conditional segue performed on tap on UITableViewCell