How to obtain data passed in performSegueWithIdentifier - ios

This will probably take two seconds to answer, but my search skills have not gotten me very far on this issue. I am performing a segue but I'm not sure how to grab the id on the destination. Here is my code on the tableview controller.
- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath: NSIndexPath *)indexPath{
NSLog(#"reaching accessoryButtonTappedForRowWithIndexPath:");
[self performSegueWithIdentifier:#"leads_calls_to_detail" sender:[[self.leads_calls objectAtIndex:indexPath.row] objectForKey:#"ID"]];
}
What do I have to create on my destination view controller to be able to grab the id that I'm attempting to pass, or is the way I'm performing my segue incompatible with what I am attempting?

You should just pass values to the destinationViewController inside prepareForSegue: and pass self as the sender.. try using something like:
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if([[segue identifier] isEqualToString:#"leads_calls_to_detail"])
{
YourViewController *controller=(YourViewController *)segue.destinationViewController;
NSIndexPath *path = [self.tableView indexPathForSelectedRow];
//Or rather just save the indexPath in a property in your currentViewController when you get the accessoryButtonTappedForRowAtIndexPath callback, and use it here
controller.yourPropertyToSet = [self.leads_calls objectAtIndex:path.row];
}
}
And also according to Rob Mayoff, you can grab the index path for the row that the accessory was tapped at by using something like this:
NSIndexPath *indexPath = [self.tableView indexPathForCell:sender];//where sender is the sender passed in from prepareForSegue:
How to find indexPath for tapped accessory button in tableView

Related

Is using tableView:willSelectedRowAtIndexPath: correct way to pass variable?

Hello i am trying to pass variable with segue.
I am getting variable to pass with tableView:willSelectedRowAtIndexPath: is this correct way? If it is not, how should i achieve this? (Note: It is working like this.)
- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath {
selectedCoffeeShop = [coffeeShops objectAtIndex:indexPath.row];
return indexPath;
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"coffeeShopDetailSegue"]) {
CoffeeShopDetailViewController *controller = (CoffeeShopDetailViewController *)segue.destinationViewController;
[segue destinationViewController];
controller.coffeeShop = selectedCoffeeShop;
}
}
If your segue is made from the cell itself, then there is no need to implement either willSelectRowAtIndexPath or didSelectRowAtIndexPath. You only need prepareForSegue:sender: since the sender argument will be the cell, and you can use that to get the indexPath you need,
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(UITableViewCell *)sender {
if ([segue.identifier isEqualToString:#"coffeeShopDetailSegue"]) {
NSInteger row = [self.tableView indexPathForCell:sender].row;
CoffeeShopDetailViewController *controller = segue.destinationViewController;
controller.coffeeShop = coffeeShops[row];
}
}
That way to do it is absolutely fine.
Another way would be to remove the automatic segue trigger from storyboards and instead implement:
tableView:didSelectRowAtIndexPath: to call performSegueWithIdentifier:sender:.
It could look like this:
- (NSIndexPath *)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
selectedCoffeeShop = [coffeeShops objectAtIndex:indexPath.row];
[self performSegueWithIdentifier:#"coffeeShopDetailSegue" sender:self];
return indexPath;
}
In that case you still need your implementation of prepareForSegue:sender:.
You could also do it completely without segues, using UINavigationController, but then you'd have to instantiate the CoffeeShopDetailViewController programmatically as well.
Your approach is perfectly fine though!
As noted in the comments, you can remove [segue destinationViewController];, since this returns the destination view controller which you already saved in the variable controller in the line right above. :)

prepareforSegue method on UITableViewControllers

I used two tableviewcontrollers,i want to display country names array data in
first tableviewcontroller (recipeBookTableViewController) and other capital array data in second tableviewcontroller (RecipetableviewController),
when a first tableviewcontroller cell is clicked it should move to second tableviewcontroller with capital array data.
I have taken prepareforSegue method to shift to second tableview. but the method is never called.
how to send data to next tableview.
RecipeBookViewController(table1) Recipetableview(table2)
INDIA (cell) ------------> Delhi(cell)
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"showRecipeDetail"])
{
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
RecipeDetailViewController *destViewController = segue.destinationViewController;
destViewController.second = [onew objectAtIndex:indexPath.row];
NSLog(#"%#",onew);
NSLog(#"data is %#",destViewController.second);
// destViewController.lable2 = [derivationArray objectAtIndex:indexPath.row];
// destViewController.image = [iconArray objectAtIndex:indexPath.row];
}
}
Problem is in creating segue.
Make sure you have created segue from cell of first table to second viewController.
Name the segue as showRecipeDetail.
Look at the image below:

didSelectRowAtIndexPath and prepareForSegue implementation

I have two methods :
- (void)tableView: (UITableView *)tableView didSelectRowAtIndexPath: (NSIndexPath *)indexPath
{
testNumber=indexPath.row;
testNumber=testNumber+1;
NSLog(#"Test number : %i",testNumber);
}
then
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if ([[segue identifier] isEqualToString:#"testStart1"])
{
tViewController *tvc = [segue destinationViewController];
tvc.testNumberTVC=testNumber;
}
}
I have got also a segue who is triggered by selecting a row in my UITableView.
My problem is when I select a row, prepareForSegue is acting before didSelectRowAtIndexPath so the new value of testNumber is not transferred.
I would like to implement prepareForSegue only when didSelectRowAtIndexPath is done or better:
Transfer the value of testNumber using only didSelectRowAtIndexPath method and so removing prepareForSegue method.
I've seen few topics about transfering data from UITableView to DetailView but with the new xCode 5, when an error message appears, I don't really know if this is because solution is outdated or if there is a real error is my code.
You could create your segues between the view controllers rather than from cell selection and set the identifier of the segue in the storyboard. Then you could do something like this:
- (void)tableView: (UITableView *)tableView didSelectRowAtIndexPath: (NSIndexPath *)indexPath
{
testNumber=indexPath.row;
testNumber=testNumber+1;
NSLog(#"Test number : %i",testNumber);
[self performSegueWithIdentifier:#"mySegueIdentifier" sender:self];
}
Another option would be to check out the answer to this link here. Basically you can get the cell indexPath in prepareForSegue like this:
UITableViewCell *cell = (UITableViewCell*)sender;
NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];

Using PFQueryForTableViewController and capturing information for segue at table cell

so I am using a PFQueryForTableViewController class connected to my storyboard. I use the queryForTable method to get the information in the back, but the information is in a different order every time that the user queries for the table. When the user presses on the cell it segues to another viewController. I need to retain the information at that cell when the user presses the cell to fill in the information on the next view controller. I am currently using the tableView: didSelectRowAtIndexPath: object: method, as well as the prepareForSegue: method. I am not sure how to retain the information, and with the code I am currently running, I am getting the error:
"'NSInvalidArgumentException', reason: '-[UITableViewCell objectAtIndex:]: unrecognized selector sent to instance 0x9b6e420'"
Here is the code for the segue:
- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[super tableView:tableView didSelectRowAtIndexPath:indexPath];
self.selectedCell = indexPath;
[self performSegueWithIdentifier:#"profile" sender:[self.objectId objectAtIndex:self.selectedCell.row]];
}
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"profile"]) {
ProfileViewController *userInfo = [segue destinationViewController];
userInfo.userInfo = [NSMutableArray arrayWithArray:sender];
}
}
Using sender for passing this information is not good practice. Instead, I would use a private property in the table view and setting this when you select the row.
In didSelectRowAtIndexPath:
self.currentProfile = [self objectAtIndexPath:indexPath];
[self performSegueWithIdentifier:#"profile" sender:self];
Then, in prepareForSegue:
ProfileViewController *userInfo = [segue destinationViewController];
userInfo.user = self.currentProfile; // Or, if you want to pass user details as array, create array here

How to segue from a UISearchBarDisplayController result to a detailViewController

So, using storyboard you can create a segue from the UITableViewCell from the first tableViewController to a detailViewController.
Not too complicated, however, when a UISearchBarDisplayController is introduced into the storyboard mix, how can you segue the results cell to the detailViewController?
I am able to search without a problem, I followed this tutorial: http://clingingtoideas.blogspot.com/2010/02/uitableview-how-to-part-2-search.html
All I can do is select a row from the search, it turns blue and doesn't go to the detailViewController.
I have implemented the method prepareForSegue, which works for the non searched cells, but can't figure out this one.
Here's the solution that's based on the comment by #James Chen. Also using a different IndexPath depending on which state the table is in.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"toDetail"]) {
Person *person = nil;
if (self.searchDisplayController.active == YES) {
NSIndexPath *indexPath = indexPath = [self.searchDisplayController.searchResultsTableView indexPathForSelectedRow];
NSLog(#"segue - section: %d, row: %d", indexPath.section, indexPath.row);
person = [self.filteredPersonArray objectAtIndex:indexPath.row];
}
else {
NSIndexPath *indexPath = indexPath = [self.tableView indexPathForSelectedRow];
NSLog(#"segue - section: %d, row: %d", indexPath.section, indexPath.row);
person = [self.personArray objectAtIndex:indexPath.row];
}
[[segue destinationViewController] setPerson:person];
}
}
I tried your solution and found that prepareForSegue is called twice
due to the life cycle and didSelect... -> performSegueWithIdentifier.
self:prepareForSegue: object on destination controller is set
(with wrong index) because
dest:viewDidLoad: the destination controller view is loaded after which
self:didSelectRow...: the index is known and properly set.
self:prepareForSegue: object is now correct but has no side effect.
I then focused on didSelect... and came up with this solution where I deleted the segue and pushed the view programmatically:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
DestTableViewController *controller = [self.storyboard instantiateViewControllerWithIdentifier:#"DestViewController"];
CustomObj *custObj = nil;
if (tableView == self.searchDisplayController.searchResultsTableView) {
custObj = [filteredListContent objectAtIndex:indexPath.row];
} else {
storeToDetail = [self.fetchedResultsController objectAtIndexPath:indexPath];
}
controller.custObj = custObj;
[self.navigationController setNavigationBarHidden:NO];
[self.navigationController pushViewController:controller animated:YES];
// presentViewController::animated:completion is always full screen (see problem below)
}
I then experienced some problems going back because I follow a segue
from a mapView, which lead to:
//DestinationViewController
- (IBAction)back:(id)sender
{
[self.navigationController popToRootViewControllerAnimated:YES]; // list
[self.presentingViewController dismissViewControllerAnimated:YES completion:nil]; // map
}
which is not the way to do it but for now it works.
However, the first part is easy and clean, and maybe it works for you too?!
Ok I think I got it, it seems like a bit of a hack but it works for my purposes:
I am using storyboard:
I have a UITableview controller with UISearchBarDisplayController directly on top of it. No code just drag and drop.
From there, I followed this tutorial to get the search bar to search correctly http://clingingtoideas.blogspot.com/2010/02/uitableview-how-to-part-2-search.html
However prepareForSegue: would only let me display a cell from the original array, not with the search array.
So I used didSelectRowAtIndexPath:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (savedSearchTerm) {
searchRowSelected = indexPath.row; //<-- the trick that worked
[self performSegueWithIdentifier:#"ShowDetail" sender:self];
}
}
searchRowSelected is an int variable that I declared at the top of the class.
didSelectRowAtIndexPath: knew which row I was selecting, but prepareForSegue didn't. Thats why I needed that variable.
This is how I used it in prepareForSegue:
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if ([segue.identifier isEqualToString:#"ShowDetail"]) {
dvc = [segue destinationViewController];
NSIndexPath* path = [self.tableView indexPathForSelectedRow];
int row = [path row];
if (savedSearchTerm){ //set the detailViewController with the searched data cell
myDataClass* c = [searchResults objectAtIndex:searchRowSelected];
dvc.myDataClass = c;
}else{ //set the detailViewController with the original data cell
myDataClass* c = [array objectAtIndex:row];
dvc.myDataClass = c;
}
}
}
Also use this code to clean up savedSearchTerm
-(void) searchDisplayControllerWillEndSearch:(UISearchDisplayController *)controller{
[self setSavedSearchTerm:nil];
}
If anyone has a better solution I'm all ears :)

Resources