I am using UITableViewController and on selection of row from the list i want to open another scene and send the info of the selected row. I got one link and i followed that and also i attched say Segue1 to segue2 in push mode. but when i am executing it is throwing error for no such segue associated with segue1.
below is the code for Row Selection:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"index is %ld",(long)indexPath.row );
[self performSegueWithIdentifier:#"Put_Controller" sender:indexPath.self];
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"Put_Controller"])
{
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
NSDate *object = _objects[indexPath.row];
[[segue destinationViewController] setDetailItem:object];
}
}
Don't forget to set storyboard segue identifier:- Put_Controller
have you checked that the name is set properly between the scenes?
Actually i was not setting the identifier in the attributes Inspector and that i got from the link attached and now its working ::http://prateekvjoshi.com/2013/11/02/how-to-trigger-a-segue-programmatically-in-ios/
Related
I am trying to push data from a UITableViewCell into another view controller. I have tried two separate ways, instantiateViewControllerWithIdentifier and also PrepareForSegue. In both instances the ViewController loads correctly but the data is not being passed across (either null, or the first array value).
Here is my instantiateViewControllerWithIdentifier method, when I log the variable within my ViewController it just returns null.
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *testNumber = [jobNumberArray objectAtIndex:indexPath.row];
NSLog(#"Job is... %#",testNumber);
StandardInfoViewController *controller = [self.storyboard instantiateViewControllerWithIdentifier:#"StandardInfoViewController"];
controller.JobNr = [jobNumberArray objectAtIndex:indexPath.row];
[self.navigationController pushViewController:controller animated:YES];
}
Prepare For Segue
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[self performSegueWithIdentifier:#"Details" sender: self];
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if([segue.identifier isEqualToString:#"Details"]){
StandardInfoViewController *controller = (StandardInfoViewController *)segue.destinationViewController;
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
controller.jobNumber = [jobNumberArray objectAtIndex:indexPath.row];
}
}
When I use the prepareForSegue call I get the first row of my Array, which I understand because it doesn't know the cell, but I don't know how to identify the Cell within the prepareForSegue call.
I hope this makes sense, and any help or pointers would be greatly appreciated.
Thanks
If you drag the segue FROM the tableView-cell in the storyboard, you will then get the cell itself as parameter sender.
then you can use tableView indexPathForCell:sender to get the actual index of the selected cell. Then just fetch your object normally.
I.e. you will not need to implement didSelectRowAtIndexPath
If you still want to use didSelectRowAtIndexPath, just pass the cell as the sender parameter manually. I.e:
[self performSegueWithIdentifier:#"Details"
sender:[self.tableView cellForRowAtIndexPath:indexPath]]
Although your first version with instansiateViewController should work, judging by your code.
Another pattern is to subclass the cells themselves, and let them have a property that is the object that they want to display. Then you can just fetch the object directly from the cell without calling the data-array itself.
Is this what you want?
This is how you identify Cell in prepareForSegue method.
**UITableViewCell *cell=[myTable cellForRowAtIndexPath:path];**
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if([segue.identifier isEqualToString:#"Details"]){
StandardInfoViewController *controller = (StandardInfoViewController *)segue.destinationViewController;
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
**UITableViewCell *cell=[self.tableView cellForRowAtIndexPath:indexPath];**
controller.jobNumber = [jobNumberArray objectAtIndex:indexPath.row];
}
}
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 HomeTableViewController which consists of two sections. When you click on ANY cell, it directs the user to the DetailsViewController. The DetailsViewController has 2 labels. One in the cell number, the other is the due date. To direct my cell to my details view controller I have the following code: This is in my HistoryTableViewController.m
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// HistoryDetailsViewController *HDV = [self.storyboard instantiateViewControllerWithIdentifier:#"HistoryDetails"];
// [self.navigationController pushViewController:HDV animated:YES];
NSLog(#"index path section--%i",[indexPath section]);
[self performSegueWithIdentifier:#"Push" sender:indexPath];
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if ([[segue identifier] isEqualToString:#"Push"]) {
HistoryDetailsViewController *detailVC=(HistoryDetailsViewController*)segue.destinationViewController;
}
}
Now that I'm able to access my DetailsViewController, I want to control its labels. I want to be able to modify the labels ACCORDING TO THE SECTION OF THE CELL I TAPPED ON.
However when I try something like
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if ([[segue identifier] isEqualToString:#"Push"]) {
HistoryDetailsViewController *detailVC=(HistoryDetailsViewController*)segue.destinationViewController;
detailVC.labelCellNum.text = #"Cell test";
detailVC.labelDueDate.text = #"Date Test";
}
}
I can't even modify the label's text using this code. I don't understand.
All help is appreciated, thanks in advance.
The way I would do it would be to have a property for each string you'd like to use in the detail view: (declared in .h)
#property (nonatomic, strong) NSString *stringOne;
Then in the prepareForSegue, I would assign a certain value to it:
[detailVC setStringOne:#"Some string"];
And in the viewDidLoad method of the Detail VC, I'd set that string somewhere I want to use it:
[self.labelCellNum setText:self.stringOne];
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];