I have a UICollectionView that segues to a Detail VC. The segue goes from custom cell to the detail.
I read here stackoverflow link that you can't use prepareForSeguethat you must use performSeguein didSelectItem
The issue is, I need to pass data. I tried using prepareForSegue anyways, but the cells are now not selectable. Ideas?
- (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];
NSLog(#"collectionView imageview %#", destViewController.thumbnailView);
destViewController.usernameLabel.text = [image valueForKeyPath:#"user.username"];
destViewController.locationLabel.text = [image valueForKeyPath:#"location.name"];
destViewController.captionString = image.caption;
}
}
Then I tried this with performSegue in didSelectItem and I created a method createLocationImageto call the detail VC to make a LocationImage in it's implementation, but the createLocationImage never gets called
-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{
LocationImage *testImage = (LocationImage*)self.savedItems[indexPath.row];
[self.diaryDetailVC createLocationImage:testImage];
[self performSegueWithIdentifier:#"detailSegue" sender:self];
}
Related
This question already has answers here:
How to get indexpath in prepareForSegue
(4 answers)
Closed 6 years ago.
I have a TableViewCell with CutomCells,that includes images view, when user selects some row, the image that is in this row should be shown in another viewController.
Connection among these Controllers is done through segue, where I tries to set the image.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"ImageVC"])
{
ImageViewController * ivc = segue.destinationViewController;
ivc.myTemporaryImage = [self.dataDictionary objectForKey:self.names[self.selectedCell]];
}
}
to define which one row was selected I use TableViewDelegates method:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
self.selectedCell = indexPath.row;
[self.dataDictionary objectForKey:self.names[indexPath.row]];
}
The issue here that image is not reflected, cause firstly fires method: prepareForSegue, and only after that - didSelectRowAtIndexPath. But I need to change this order. Could you advice how to do this?
Also I tried to create ImageViewController programmatically, without using segue, directly in method didSelectRowAtIndexPath, but in this image is not shown in this case.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[self.dataDictionary objectForKey:self.names[indexPath.row]];
ImageViewController * ivc = [[ImageViewController alloc]init];
ivc.myTemporaryImage = [self.savedImages objectForKey:self.names[indexPath.row]];
[self.navigationController pushViewController:ivc animated:YES];
}
Could you please how to manage this issue?
You have to remove the direct reference to your segue in your cell, then, in your tableView delegate call it programmatically:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
self.selectedCell = indexPath.row;
[self performSegueWithIdentifier:#"ImageVC", sender: [self.savedImages objectForKey:self.names[indexPath.row]]]
}
Then in prepareForSegue:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"ImageVC"])
{
ImageViewController * ivc = segue.destinationViewController;
ivc.myTemporaryImage = sender;
}
}
I think you can save the indexPath at the willSelectRowAtIndexPath method.
I am parsing xml image urls to imageview in detailviewcontroller but I passed the images through the shareddelegate.but when i click on the tableviewcell only few images occure in detailviewcontroller.
imageview.image = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:sharedDelegate.imagObj]]];
the above code I wrote in detailviewcontroller
AppDelegate *sharedDelegate = (AppDelegate*)[[UIApplication sharedApplication]delegate];
sharedDelegate.imagObj = [Imagesarray objectAtIndex:indexPath.row];
I wrote this code in tableview didselectrow method.
It would make your code easier to read and maintain, if you pass the data to your detailViewController in a property.
This will help detailViewController to be more self-contained, and limit what it can mutate.
Add a property to your DetailViewController for the data you want to pass. It sounds like you want to pass an array of image URLs, so add an array property:
#property (nonatomic, strong) NSArray *images;
In prepareForSegue:sender:, set the DetailViewController's passed images to the values associated with the selected row:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)__unused sender
{
if ([[segue identifier] isEqualToString:#"showDetail"])
{
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
DetailViewController *controller = (DetailViewController *)[segue destinationViewController];
controller.images = ...;
}
}
You don't need to have a tableView:didSelectRowAtIndexPath: method, if you create a push segue from a tableViewCell to DetailViewController within Storyboard. Give the segue an identifier (such as "showDetail"). Then in prepareForSegue, you pass the necessary data, as mentioned.
You can create a image property in DetailViewController
And from tableview didSelectRowAtIndexPath method. call the segue
[self performSegueWithIdentifier:#"DetailSegue" sender:indexpath];
and set it from
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"DetailSegue"])
{
DetailViewController *dc = (DetailViewController *)[segue destinationViewController];
dc.image = [imagesarray objectAtIndex:sender.row];
}
}
I have UITableViewController, when I tapped one cell I want to show UINavigationController with UITableViewController as modal view.
I have this function to prepare seque:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"ShowTitles"]) {
UINavigationController *navigationController = (UINavigationController *)segue.destinationViewController;
if (navigationController) {
DataListViewController *dataListController = (DataListViewController *)[navigationController topViewController];
if (dataListController) {
dataListController.delegate = self;
dataListController.viewTitle = NSLocalizedString(#"Titles", nil);
dataListController.dataArray = [NSMutableArray arrayWithArray:self.titles];
}
}
}
}
But when I tap on the cell I get this error: CATransaction synchronize called within transaction.
What could cause that error?
EDIT:
it happens in this place in cellForRowAtIndexPath function:
[tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
I didn't notice that for the function dequeueReusableCellWithIdentifier:forIndexPath: I have to register the class, so I did it in the viewDidLoad function:
[self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:CellIdentifier];
I do have a UITableViewController which can be edited.
I do have 2 Segues in my Storyboard, coming from the tableView going to an EditViewController (via modal) and the second one via Push to the DetailViewController.
I want, when the tableview isEditing, that the segue to editviewcontroller is executed, and when is not editing, than to DetailViewController.
I tried different ways, with the prepareforsegue method. then several tries with the didselectrowatindexpath method, where I stand now.
Now, when the tableView is in editing and I touch one cell, the detailviewcontroller pushes and on top of this the editviewcontroller comes in as modal view controller.
Here is my code.
Can you please give me hints:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSLog(#"didSelectRowAtIndexPath %i", indexPath.row);
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
if (tableView.isEditing == FALSE) {
NSLog(#"isediting");
[self performSegueWithIdentifier:#"showDetail" sender:cell];
} else {
[self performSegueWithIdentifier:#"showEditPerson" sender:cell];
}
}
and here is what i have tried with the prepare for segue method:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([[segue identifier] isEqualToString:#"showDetail"]) {
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
NSDictionary *theChild = [myAppDelegate.myPersonsArray objectAtIndex:indexPath.row];
[[segue destinationViewController] setDetailItem:theChild];
}
if ([[segue identifier] isEqualToString:#"showEditPerson"]) {
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
NSDictionary *theChild = [myAppDelegate.myPersonsArray objectAtIndex:indexPath.row];
[[segue destinationViewController] setDetailItem:theChild];
}
}
From my comment above:
It seems you have the prototype cell hooked up to a segue in addition to the delegate method. Fix the segue connections and you should be all set.
So I have a UITableView, and the cells are connected to a UIStoryboardSegue in order to open a new UIViewController. After clicking a cell prepareForSegue get's called and everything works fine.
QUESTION: In the follwoing method how can i know what is the indexPath of the selected cell in my TableView?
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
ObjectDetailViewController *mvc = [segue destinationViewController];
// PassingObject *obj = [self.array objectAtIndex: ? ];
mvc.passingObject = obj;
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// Assume self.view is the table view
NSIndexPath *path = [self.tableView indexPathForSelectedRow];
DetailObject *detail = [self detailForIndexPath:path];
[segue.destinationViewController setDetail:detail];
}
Instead of [self.tableView indexPathForSelectedRow] (look at the DJPlayer answer) you can use [self.tableView indexPathForCell:sender], since sender is a selected cell in this case.