I have 2 view controllers - One with a collectionView displaying images, the other it's corresponding detail view - pretty basic. The problems is items in collectionView are not selectable for some reason (touch but nothing happens). Also, I am not using a nav controller to embed the collectionView VC in, prefer to use an unwind segue with custom button - will this work?
I made a connection from the collectionView Cell to the Detail VC.
In prepareForSegue
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"detailSegue"]) {
LPDiaryDetailViewController *destViewController = segue.destinationViewController;
NSIndexPath *indexPath = [self.collectionView indexPathForCell:sender];
LocationImage *image = self.savedItems[indexPath.row];
destViewController.captionString = image.caption;
}
}
The cell is probably not responding to touches because you haven't set the image view's userInteractionEnabled property to YES (it's NO by default).
You can't use an unwind segue to go forward; they're for going back to a previous controller, so your preference to use an unwind segue doesn't make sense. Do you mean for the unwind segue to be used for going back from the detail VC? It's not clear where you want this custom button. You already have the segue connected from the cell, so you don't need a button to invoke the segue.
Related
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.
this is my problem. I can perfectly show a detailedViewController came from a table view, but i got 2 more tableview that i want to make it seem in detailed.When i gave it same variables - since every things that came same - it still doesn't go to the next view controller.I checked segue identifier aswell and i really don't want to make a new detailed controller.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"showDetail"]) {
// Get destination view
detailViewController *destViewController = [segue destinationViewController];
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
NSInteger tagIndex = [(UIButton *)sender tag];
destViewController.recipeName =[[self.content objectAtIndex:indexPath.row] valueForKey:#"recipeName"];
destViewController.recipeDetail =[[self.content objectAtIndex:indexPath.row] valueForKey:#"recipeDetail"];
this is how i pass the data.They are exactly same with a small difference. The content of the content array.
You can go to the same view controller from multiple other controllers. You may be able to do this by simply creating the segue from the appropriate cells in each table. The way I've done it is to create a segue from each table view controller to the "detail" view controller, and then perform the segue in code when the appropriate cell is selected. Keep in mind that when creating segues in IB, there is a difference between creating them from table view cells and from the view controllers themselves.
So I got a ViewController with 4 seperate buttons. When clicking on button1 TableViewController1 pops over the ViewController with a list of items. When selecting an item the TableViewController1 drops down and button1 now has the text that was selected in the table. This is all good. But when I do the exact same thing for button2 with TableViewController2 the data from button1 is reseted.
I use segues with identifiers, some of the code:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"showEducation"]) {
NSIndexPath *indexPath = [self.tableViewEducation indexPathForSelectedRow];
ViewController *destViewController = segue.destinationViewController;
destViewController.educationText = [tableViewArray objectAtIndex:indexPath.row];
}
}
So at the moment I got multiple segue identifiers for each button and multiple .h and .m files for the tableviews. Am I using a completely wrong technique to get this to work? I hope im clear enough, otherwise I can upload images.
Edit: I just noticed, I also have a slider on my ViewController. When clicking on a button and selecting a row in the TableView the slider gets reseted to the original position. Same problem as above kind of.
I am thinking that you're pushing to a new instance of your View Controller every time you push from either tableViewController.
Imagine that you click on one button on ViewController0, this creates an instance of tableViewController1. When you click a row, you're just using a performSegue to create a NEW instance of ViewController0, and this has its own ViewDidLoad - resetting the buttons.
(You're saying that the view "drops down", so it's modal?)
Don't use performSegue from the tableViewController back to the viewController, try using [self dismissModalViewController: withCompletion:](or something similar, can't remember), then your tableViewController should remove itself and reveal the original ViewController.
Now, you don't have a way to change the name of the button though, but that can be done by accessing the sender from the tableView, which will give you the original View Controller, and not a new instance of it.
One way of getting the sender is to use [performSegue... from ViewController0, and in it's own prepareForSegue, you could do something like
//In the first ViewController, not in the TableViewControllers
-(void)prepareForSegue:(UIStoryboardSegue*)segue sender:(id)sender{
if(sender == button1)
{
UITableViewController1 *dest = segue.destinationViewController;
[dest setSender: self];
}
}
And in TableViewController1 you'd create a variable ViewController *home;, and a method -(void)setSender:(ViewController*)sender;, so that in your didSelectRowAtIndexPath, you could now say [[(ViewController0*)home button1]setTitle:#..];, and then [dismissModalViewController..]
There are other ways to do it as well, depending on how you are pushing from your viewController to the tableViewController. And I'm sure there are easier ways to access the sender than this, but it works and is useful if you're already sending other data.
I have been able to find tutorials on creating the transition from one tableview to another view. The transition when you click on a cell is to the same destination view controller. I was wondering how I could transition to different view controllers for each of the cells in the tableview. Can I still do this with storyboard? If so, how? If not, what alternatives can you suggest?
The storyboard has been hooked up from the tableview to a detailed view. But this is what I would like to accomplish:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"mytransition"]) {
NSInteger sectionId = [[self.tableView indexPathForSelectedRow] section];
if (sectionId == 0) {
NSLog(#"try to change the destination view controller");
//I don't know if this is possible?!
} else {
NSLog(#"Proceed with the original destination view controller");
//this is ok
}
}
}
EDIT: I found the solution! You can view it here: http://forums.macrumors.com/showthread.php?t=1274743
In summary, the solution involved using a combination of the prepareForSegue and didSelectRowAtIndexPath for anyone who's interested. Instead of linking each cell to another view, create another segue from the controller to each of the desired view controllers. Then check the segue identifier.
-Jen
Jen's right. The solution from Jen's link does work.
Create the segue from the prototype cell in the table to the destination view controller.
Set the identifier of the segue.
Modify didSelectRowAtIndexPath to get the row number of the selected cell, and call performSegueWithIdentifier with the segue identifier for that cell.
My problem seems like a generic problem, yet can't seem to find an answer for it.
I have a situation where when the user taps on a custom UITableViewCell, I would like to display an alert and then based on the response to the alert, either stay on the same view (user selecting cancel) or display another view (if the user selects proceed). And I would like to do this using the storyboard feature & segues.
How would one go about this? Do you have to do this the old fashioned way?
#user, Just create the alertView the old fashion way; I do know of any storyboard feature to do this differently. Where storyboard can help is with the segues. You can call the segues programmatically. With you alert view cancel button you can just return (i.e. do nothing). For the other option, to display another view, you can programmatically call a segue to transition to the desired view. If you don't have the proper segue already defined for some other reason on your storyboard, just create a button out and use that to create the segue and name it. Name the segue by clicking on it in storyboard and use the attributes inspector to give it name (identifier). Then hide the button or put it out of the view. I typically put these type of button on the toolbar and use spacers to keep them out of the view. Here's some sample code:
Call the segue from the alert view delegate like this:
[self performSegueWithIdentifier: #"done" sender: self];
Also implement this method to do any necessary task to prepare for the segue:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"done"])
{
// [[segue destinationViewController] setManagedObjectContext:self.managedObjectContext];
// [[segue destinationViewController] setSelectedClient:selectedClient];
}
}
You can create segues directly from the startingViewController to multiple destinationViewControllers that can then be "performed" programmatically. You do not need to create any hidden buttons for them, which does seem like a hack.
OK I came up with a solution in keeping with the storyboard that I like.
Example:
My tableview has 2 sections, grouped, and cells are dynamic prototype. Section 0 contains one row/UITableViewCell & I don't want it to segue. Section 1 contains multiple cells that I want to trigger the segue & drill down into the detail.
In Storyboard:
I removed the segue linking the tableviewcell to the destination view controller.
I made a 'generic' segue linking the source view controller directly to the destination view controller.
In the attributes on the segue, I set the identifier ('EditTimePeriod') and set the type to Push (I presume Modal would work just the same).
In the source view controller:
In the prepareForSegue method I handled both the common 'AddTimePeriod' segue I control-dragged from my UIBarButtonItem (Add), along with the 'generic'(vc-->vc) 'EditTimePeriod' segue.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// handle the click of the 'Add' bar button item
if([segue.identifier isEqualToString:#"AddTimePeriod"]) {
TimePeriodViewController* tpvc = (TimePeriodViewController*)segue.destinationViewController;
tpvc.delegate = self;
// database & entity stuff for adding the new one to the mOC, etc
}
// handle the click of one of the 'editable' cells -
if([segue.identifier isEqualToString:#"EditTimePeriod"]) {
TimePeriodViewController* tpvc = (TimePeriodViewController*)segue.destinationViewController;
tpvc.delegate = self;
TimePeriod * newTP = [self.timePeriodArray objectAtIndex:self.tableView.indexPathForSelectedRow.row];
tpvc.timePeriod = newTP;
}
}
Then I implemented the tableView:didSelectRowAtIndexPath method, and put my condition in here. If the selected row was outside of section zero I called the EditTimePeriod segue manually, defining the sender as the selected tableviewcell:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if(self.tableView.indexPathForSelectedRow.section!=0){
[self performSegueWithIdentifier:#"EditTimePeriod" sender:[tableView cellForRowAtIndexPath:indexPath]];
}
[self.tableView deselectRowAtIndexPath:indexPath animated:YES];
return;
}
would be nice to code the cell in section 0 so that it is not selectable in the first place!
Hope this helps though.
** and then 5 minutes later I took another look and realized I could just move the data from section 0 into the section header, which is more intuitive and wasn't being used anyway. leaving the design open for a standard segue from each tableviewcell without needing any condition/check. Was a good exercise anyway though :)