I have a Uitableview cell that has been successfully populated with dictionary array. Right now, i have difficulty passing the selected cell value to another view controller and display that value.
Here is my codes:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
NSLog(#"Tapped: %#",[[feeds objectAtIndex:indexPath.row]objectForKey:#"IncidentNumber"]);
someProperty = [[feeds objectAtIndex:indexPath.row]objectForKey:#"IncidentNumber"];
[self performSegueWithIdentifier:#"item" sender:self];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
if ([[segue identifier] isEqualToString:#"yourSegue"])
{
DescriptionViewController *vc;
vc = segue.destinationViewController;
vc.item_pass = someProperty;
}
}
you perform a segue with the identifier item but later in prepareForSegue you check for a segue with the identifier yourSegue...
Instead of implementing didSelectRowAtIndexPath connect the segue to the table view cell (rather than to the view controller).
Then the selected cell is passed as sender parameter in prepareForSegue and you can get the index path with
let selectedIndexPath = tableView.indexPathForCell(sender as! UITableViewCell)!
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 tableview and i want to when I touch on the cells to be navigate to the editViewController and when I Long touch (touch and wait) on the cells to be navigate to the DetailsViewController.
I got the answer to this question here.
now i have another problem, i use following code to pass selected row to detailViewContoler
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
if([[segue identifier] isEqualToString:#"ContectDetails"])
{
//get selected contact
NSManagedObject *selectedContact=[contacts objectAtIndex:[[self.tableView indexPathForSelectedRow] row]];
//pass selected contact to MyContactAppViewController for editing
ContactDetailsViewController *destViewcontroller=segue.destinationViewController;
destViewcontroller.contact=selectedContact;
//contact is my core data object
}
}
now i need to creat a modal segue and set segue identifier to "ContectDetails" in long press method.
Create a segue in storyboard between your table view's view controller and the ContactDetailsViewController and name it in the attributes inspector (let's say you name it 'ContactDetailsModalSegue').
Then in the gesture recognizer handler method you can call the segue like this:
-(void)handleLongPress:(UILongPressGestureRecognizer *)gestureRecognizer {
[self performSegueWithIdentifier:#"ContactDetailsModalSegue"
sender:self];
}
In this case self should be the view controller that your table view resides in. If you are handling the long press inside the table view cell class, then you should keep a weak reference to the table view's view controller and refactor accordingly:
In your table view cell's .h file include a pointer to the parent vc:
#property (weak, nonatomic) UIViewController *vc;
Make sure you pass a reference to the cell when you set it up in the table view delegate:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"MyIdentifier"];
cell.vc = self; //Assuming your datasource is in the view controller file (adjust if necessary)
}
and finally in the tableview cell's .m file, use the pointer to the vc to call the segue:
-(void)handleLongPress:(UILongPressGestureRecognizer *)gestureRecognizer {
[self.vc performSegueWithIdentifier:#"ContactDetailsModalSegue"
sender:self];
}
Update:
In order to pass a reference to the data that was used to populate the table view cell to the destinationViewController, you can do the following:
First, ensure that the data is stored in a model object in your custom table view cell subclass .h file. For this example I am using an NSManagedObject because thats what is in your question, but others reading this can swap this out with any model object (e.g. an NSObject subclass):
#property (strong, nonatomic) NSManagedObject *managedObject;
Note that in the performSegueWithIdentifier: method call you are passing a reference to self as the sender parameter. The object you specify for the sender parameter will be passed as an argument to the - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender method. This enables you to retrieve the public property you just added to your custom table view cell, like this:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
//Verify segue identifier
if([[segue identifier] isEqualToString:#"ContactDetailsModalSegue"])
{
//Protect yourself from unrecognized selector errors in case you reuse this segue
if ([sender isKindOfClass:[YourCustomTableCellClass class]] &&
[segue.destinationViewController respondsToSelector:#selector(setContact:)]) {
//get selected contact
NSManagedObject *selectedContact= (YourCustomTableCellClass *)sender.managedObject;
//pass selected contact to ContactDetailsViewController for editing
ContactDetailsViewController *destViewController= segue.destinationViewController;
destViewController.contact = selectedContact;
}
}
}
replace [self.navigationController pushViewController:detailView animated:YES]; with [self.navigationController presentModalViewController:detailView animated:YES completion:nil]; in the method
-(void)handleLongPress:(UILongPressGestureRecognizer *)gestureRecognizer
{
}
I have a project with a TabBar Controller with a Navigation Controller and other View Controllers on it.
In my Navigation controller i have a sequence of 3 view controller and the last of them, DetailViewController, is being presented using a modal transition. I'm parsing strings between my 2nd and 3rd view controllers, but my labels displaying the information on the 3rd one only display after selecting a cell twice, and the information that shows is the one corresponding to the first selection of the cell.
Heres my 2nd view controller (ViewController) method prepareForSegue:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
titulo=[nomeEvent objectAtIndex:indexPath.row];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if ([segue.identifier isEqualToString:#"nextView"]) {
DetailEventViewController *myVC = [segue destinationViewController];
myVC.tituloEvento = titulo;
}
}
The property tituloEvento is declared in the second view controller's .h and in viewwillappear I set my labels text.
This might be happening because prepareForSegue is getting called before didSelectRowAtIndexPath:. Here is what I would do:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if ([segue.identifier isEqualToString:#"nextView"]) {
DetailEventViewController *myVC = [segue destinationViewController];
NSIndexPath *selectedIndexPath = [self.tableView indexPathForSelectedRow];
myVC.tituloEvento = [nomeEvent objectAtIndex:selectedIndexPath.row];
}
}
I have a popover segue that goes to a view controller. I want to set some properties in the view controller when a cell is clicked. I tried using -prepareForSegue:, but then I realized that it doesn't have the scope of the selected cell. I know that I have to use:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
delegate method, but I'm not sure how that will affect the popover segue. Do I have to programatically create the popover, or is there another way?
Thanks much!
~Carpetfizz
Use self.tableView.indexPathForSelectedRow to get the data from your table's data source, e.g., the array backing the table data. If, for some reason, you don't want to get the data from your data source, then the sender is the UITableViewCell that was tapped to trigger the segue.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"YourSegueID"]) {
YourDestinationViewControllerClass* destinationController = segue.destinationViewController;
destinationController.somePublicProperty = self.yourTablesDataSourceArray[self.tableView.indexPathForSelectedRow.row];
UITableViewCell *cell = (UITableViewCell *)sender;
destinationController.someOtherPublicProperty = cell.textLabel.text;
}
}
So add an NSIndexPath propriety to your VC. Let's call it selectedCell. In your tableView:didSelectRowAtIndexPath method, save the selected index path to the instance variable.
Then in your prepareForSegue method, use the instance variable.
Alternately, in your prepareForSegue method, you could ask the table view for the currently selected row using the table view's indexPathForSelectedRow method.
The best approach is to use the indexPathForSelectedRow property.
For example you can write a code like this:
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"YourSegueIdentifier"])
{
NSIndexPath *indexPath = [sender indexPathForSelectedRow];
NextViewController *vc = (NextViewController *)segue.destinationViewController;
vc.yourProperty = #"Some Value";
}
}
Assuming NextViewController as your segue destination controller and yourProperty as the property you want to set during the segue, you can access and set information from your parent controller because indexPathForSelectedRow automatically knows which cell has been clicked.
More information can be found here.
From my TableView I dynamically want to show either a TableView or a DetailView (new segue), based on the cell's content. I setup two segues from the TableView to different DetailViews and one segue from the TableViewCell to the TableView.
I have almost completed the implementation using performSegueWithIdentifier: (see below), but there is one struggling issue remaining: after I call [self dismissModalViewControllerAnimated:YES]; on the DetailView it returns to an empty TableView . I assume because the Storyboard segue from the UITableViewCell is performed. By clicking the back button I return to my original (parent) TableView data.
Any suggestions for this work?
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
NSLog(#"%s", __PRETTY_FUNCTION__);
NSString *type = [[self.dataController objectInListAtIndex:[self.tableView indexPathForSelectedRow].row] valueForKey:#"cell_type"];
NSLog(#"cell_type: %#", type);
if([[segue identifier] isEqualToString:#"DetailSegue"])
{
UIViewController *detailViewController = [segue destinationViewController];
detailViewController.game = [self.dataController objectInListAtIndex:[self.tableView indexPathForSelectedRow].row];
} else if ...
} else if([[segue identifier] isEqualToString:#"TableViewSegue"]){
if([type isEqualToString:#"TableView"]){
//Create child ViewController, a custom ViewController with custom initWithId:Title:
CategoryViewController *categoryViewController = [[segue destinationViewController] initWithId:categoryId Title:categoryTitle];
}
}
}
I would create in my tableview multiple cells. Each with its own identifier. Then connect each cell to its own detailviewcontroller. You can also connect a cell to its own view controller (creating drill down functionality for only specific cell).
Thats all...