I have a UITableView with a custom table cell which has several controls on it - one of them is a button.
When clicking the cell itself I'm sending some data via a segue to a view controller - that works fine.
I want to open a different view controller when the button form inside the cell is clicked - and again, send some data.
The button is connected to the view controller which is opening fine when the button is clicked.
The problem is I can't get the IndexPath inside the prepareForSegue in order to set the parameter I wish to send to the view controller.
This code brings the first object from the table datasource:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if([segue.identifier isEqualToString:#"CommentSegue"])
{
NSIndexPath *path = [self.tableView indexPathForSelectedRow];
NSDictionary *detail = [myObject objectAtIndex:path.row];
CommentViewController *navController = segue.destinationViewController;
navController.data=detail;
}
}
While I want the n item which the button belongs to...
Thanks.
You should never call a segue from within the cell itself.
You have to define a target for the button in -tableView: cellForRowAtIndexPath: when populating the data for the cell.
do this:
[cell.theButton addTarget:self action:#selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];
and to get the index of the row that button belongs to, use this trick:
cell.theButton.tag = indexPath.row
you can then handle the click on your table view controller like this:
-(void) buttonClicked:(UIButton *) button
{
NSInteger index = button.tag;
// now prepare the data and perform segue
}
Related
I have two view controllers
View Controller A
View Controller B
I have a Table View in View Controller A that lists out four sounds. When a user selects one of the sounds, a button in View Controller B should be programmed to play that sound.
I have been playing around with prepareForSeque and didSelectRowAtIndexPath and can't seem to get either one to work correctly.
What is the best way to do this?
You have to keep track of the selected indexPath in didSelectRowAtIndexPath:. A simple way is to create a property:
#property (strong, nonatomic) NSIndexPath *selectedIndexPath;
And then store the selected indexPath in that property, after that, call to the performSegueWithIdentifier:sender: method:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
self.selectedIndexPath = indexPath;
[self performSegueWithIdentifier:#"SEGUE_ID" sender:nil];
}
In prepareForSegue: get the selected sound form the sounds array:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"SEGUE_ID"])
{
ViewControllerB *controller = segue.destinationViewController.
controller.selectedSound = self.sounds[self.selectedIndexPath.row];
}
}
That is in case that the name of the array is sounds. You have to create a property in the view controller B to store the sound passed through the segue. Name a segue between the scenes with the name SEGUE_ID. It is obvious that you have to adapt the code to your needs, I'm assuming your array is full of NSString objects referencing the names of your sounds. So, the property selectedSound in the last chunk of code have to be an NSString. As I said, it depends of the structure of your array of sounds.
Edit: According to the #jlehr comment, the code can be more concise by removing the property in the View Controller A, the line self.selectedIndexPath = indexPath and obtaining the selected indexPath with the following instead:
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
ViewControllerB *controller = segue.destinationViewController.
controller.selectedSound = self.sounds[indexPath.row];
I created a segue from the table view cell (in a master view controller) to a view controller and gave the segue the name "ShowDetail". In prepareForSegue in the master view controller, I setup this code, however if I touch the table view cell in the master list, nothing happens, not even the first log statement gets triggered. when I right click the table view cell in the master view controller, it shows that there's a segue wired up.
Is there a method that needs to be implemented in the master view controller to make the cell response to a touch? or is there another explanation why this might be happening?
-prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
NSLog(#"prepare for segue");
if ([[segue identifier] isEqualToString:#"ShowDetail"]){
NSLog(#"in segue to display edit");
DisplayEditViewController *devc = (DisplayEditViewController *)[segue destinationViewController];
// devc.delegate = self;
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
Event *selectedJoke = (Event *)[self.fetchedResultsController objectAtIndexPath:indexPath];
devc.currentJoke = selectedJoke;
devc.mood = selectedJoke.mood;
devc.delegate = self;
devc.mnemonicField = selectedJoke.mnemonic;
devc.jokeField = selectedJoke.joke;
}
Update 2
here's a compressed version of the project. As you see, my project lets me add new entries but not display them in the DisplayEditViewController https://dl.dropboxusercontent.com/u/10328969/preppyspeech.zip
Update 3
Even when I implement didSelectRowAtIndexPath in the masterviewcontroller, it (didSelectRowAtIndexPath) is not getting called when I click on the cell. See updated project here https://dl.dropboxusercontent.com/u/10328969/preppyspeech2.zip
I have seen you Project, there is simple mistake, the Selection type for UITableView in MasterViewController is set to No Selection, so didSelect method for UITableView doesn't work, change it from image below
And it works.
Cheers.
Maybe I didn't ask it properly, because I'm not really sure how, so I will explain myself:
I have a simple notes app with two VC's:
table view controller - to list all the notes.
view controller - to create new notes.
In the table vc I have an unwindToList method that create an instance of the create notes page to get the note object that will be passed and if its not nil I will add it to the notes array and reload the data;
- (IBAction) unwindToList: (UIStoryboardSegue *) segue
{
NMCreateNotesViewController *source = [segue sourceViewController];
NMNote *note = source.note;
if (note != nil) {
[self.notes addObject:note];
[self.tableView reloadData];
}
}
and an prepareForSegue method that will identify if this segue is a note segue (this is the segue I JUST want to preform editing in the create note page and when a user taps the save button, to save it in the same cell that the segue came from...):
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(UITableViewCell *)sender
{
if ([[segue identifier] isEqualToString:#"noteSegue"]) {
NMCreateNotesViewController *destination = [segue destinationViewController];
NSInteger indx = [self.tableView indexPathForCell:sender].row;
NMNote *note = self.notes[indx];
destination.passedInString = note.content;
}
}
In the view controller that create the notes I have a prepareForSegue method that looks like this:
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if (sender != self.saveButton) return;
if (self.textField.text.length > 0) {
self.note = [[NMNote alloc] init];
self.note.content = self.textField.text;
}
}
Now, my problem is that when i'm editing a note from the noteSegue i'm creating a new note with the edited content instead of populating the same cell of the segueNote with the new edited content...
this is how the problem looks like:
Please help me to figure this out :/
Appreciate it!
I don't quite understand your explanation.
You have a table view controller that is a master view controller and a note view controller that is a detail view controller.
The usual way to handle communications back from a detail view controller to it's master is to set up a delegate.
Define a delegate property in the detail (notes) VC that will point back to the master.
In the master's prepareForSegue, set destination.delegate = self.
Then, define a protocol for the delegate that the detail view controller will use to tell the master that the contents of a list item has changed.
You will probably need to tell the detail view controller the indexPath of the item that's being edited in the master-to-detail segue, and then before unwinding to the master, invoke a delegate method that gives the edited item to the master, along with it's indexPath so the master can save the changes and redisplay that cell.
I have a simple storyboard file with a table view inside a navigation controller. If you cick one of the cells it goes to the details view. Great.
Then I tried adding a toolbar button and hooking it up to my table view controller. The button and the seque seems to work fine, except now, when i click on one of the table cells, the modal view is triggered.
So it seems I have done something wrong, but I don't understand what.
// called by pressing the add button in the toolbar
- (IBAction)showAddEventView:(id)sender {
[self performSegueWithIdentifier:#"showAddEvent" sender:sender];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"showAddEvent"]) {
AddEventVC *addEventVC = [[AddEventVC alloc] init];
// set some property
} else {
EventIndexVC *eventIndexVC = [segue destinationViewController];
eventIndexVC.eventTitle = [self.events objectAtIndex: [[self.tableView indexPathForSelectedRow] row]];
}
}
I am creating a news app that has title, description, video and details.
this is displayed on UIViewCell on TableView, when a user clicks on that
particular cell, corresponding news is displayed as shown below
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NewsViewController *newsdetail = [[NewsViewController alloc] initWithNibName:#"NewsDetailView" bundle:nil];
self.newsdetails = detail;
[detail release];
newsdetails.title = [NSString stringWithFormat:#"%#",[titleData objectAtIndex:indexPath.row]];
newsdetails.itemID = [NSString stringWithFormat:#"%#",[NewsIds objectAtIndex:indexPath.row]];
[self.navigationController pushViewController:newsdetails animated:YES];
}
The variables (which hold JSON data) are properly defined in NewsViewController and synthesised as follows
NSMutableArray *NewsIds;
NSMutableArray *titleData;
NSMutableArray *descriptionData; etc
Now, what I want is to add a video button as shown on the storyboard, so that a user can click it and be able to see details of corresponding video through modal /popup
any suggestions or help?
In the Storyboard, just use an Action segue on the UIButton and select modal. Control Drag from the button to the Video Details VC. Give that segue a name, let's say
playVideo
Then inside the prepareForSegue method in your PlayersViewController.m you just add this:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"playVideo"]) {
// set properties on your destinationVieController to pass the data you need
}
}
Also use unwind segues on the buttons 'Cancel' and 'Done' in your destination VC to return to the previous TVC. Alternatively you could also use dismissViewControllerAnimated: that will be passed to the calling VC.
you should have a custom table view cell which will be handling actions and data on cell.