NSIndexPath 2 indicies - objective-c

I'm doing something that involves a collection view with photos in it, and upon selecting one of the cells, it will segue into a new view where it shows a larger image.
Heres prepare for segue
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if ([segue.identifier isEqualToString:#"showPhotoSegue"]) {
NSIndexPath *ip = [self.photoCollectionView indexPathForCell:sender];
PhotoDisplayViewController *viewController = segue.destinationViewController;
Photo* photo = [self.fetchedResultsController objectAtIndexPath:ip];
NSLog(#"setting PHOTO at indexPath %#", ip);
[viewController setPhoto:[UIImage imageWithContentsOfFile:photo.url]];
}
}
And heres didSelectItemAtIndexPath
-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{
NSString *identifier = #"showPhotoSegue";
[self performSegueWithIdentifier:identifier sender:self];
NSLog(#"Selected item at %#", indexPath);
}
My view is always empty so i added the print line statements, and it seems the output is always something like
Selected cell at <NSIndexPath 0x1e084940> 2 indexes [0, 0], detail view controller
So my question is, why is NSIndexPath always a pair of 2 indicies, and also how do i use it in my prepareforsegue to set the view for the segue
Thanks

In prepareForSegue:sender:, you expect sender to be a UICollectionViewCell.
In collectionView:didSelectItemAtIndexPath:, you are passing self (your UICollectionViewDelegate) as the sender argument. I suspect your collection view delegate is not a collection view cell.
Instead of sending the collection view delegate as sender, and expecting to receive a cell as sender, why not pass the index path as sender and expect to receive it as sender?
static NSString const *kShowPhotoSegueIdentifier = #"showPhotoSegue";
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
[self performSegueWithIdentifier:kShowPhotoSegueIdentifier sender:indexPath];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:kShowPhotoSegueIdentifier]) {
[self prepareForShowPhotoSegue:segue withIndexPath:sender];
}
}
- (void)prepareForShowPhotoSegue:(UIStoryboardSegue *)segue withIndexPath:(NSIndexPath *)indexPath {
PhotoDisplayViewController *viewController = segue.destinationViewController;
Photo* photo = [self.fetchedResultsController objectAtIndexPath:indexPath];
[viewController setPhoto:[UIImage imageWithContentsOfFile:photo.url]];
}

NSIndexPath is a file structure that is used to represent directory trees. In the context of a table (indexPathForCell:) it contains a section & row index.
Each index in an index path represents the index into an array of
children from one node in the tree to another, deeper, node. For
example, the index path 1.4.3.2 specifies the path shown in Figure 1.
More information in the documentation

NSIndexPath is Mainly used for UITableView Where It will Consider Section as well as Row for That..
so Where ever you want to use NSIndexPath you will be able to access
row and section for that..
so i request you to use indexpath.row for your indexing variable,
if indexpath.section is not useful for you..

Related

How to set destination view controller using indexpath value?

I have a collection view controller if the user select any cell means its need to go destination view controller.
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
cell=[collectionview cellForItemAtIndexPath:indexNumberStorager];
NSInteger indexnum;
indexnum=indexNumberStorager.row;
switch (indexnum) {
case 1:
if ([segue.identifier isEqualToString:#"Car"])
{
CarCleaningVC *dest = [segue destinationViewController];
}
break;
default:
break;
}
i tried using this code but not working properly please help me to find out the problem.
sender here is the cell that has been selected by the user (if the segue is on cell selection). You don't need to store indexPath anywhere.
Simply typecast sender into UICollectionViewCell(or your subclass if you're using any), and call indexPathForCell: on your collection view to get the indexPath.
Sample code:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
NSUInteger indexNum = [self.collectionView indexPathForCell:(UICollectionViewCell*)sender].row;
switch (indexNum)
// Relevant code
}
Also, instead of depending on the segue identifier, try to use the destinationViewController's class:
if ([segue.destinationViewController isKindOfClass:[CarCleaningVC class]]) {
//relevant code
}
You can do something like this-
in your cellForItemAtIndexPath method, set the cell tag. Something like-
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:reuseIdentifier forIndexPath:indexPath];
cell.tag=indexPath.row;
return cell;
}
And then when you cast your sender to a cell, you can just access its tag which is your Collection View's Indexpath.row.
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
UICollectionViewCell *cell=(UICollectionViewCell*)sender;
NSInteger indexnum;
indexnum=cell.tag;
switch (indexnum) {
case 1:
if ([segue.identifier isEqualToString:#"Car"])
{
CarCleaningVC *dest = [segue destinationViewController];
}
break;
default:
break;
}

Objective C - UICollectionViewController - using segues

I am lost. I have a UICollectionViewController with 4 items, each of which has an imageView and an image. I am wanting to pass the image from a selected item to a view controller:
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.item == 0)
{
[self performSegueWithIdentifier:#"FinalFace" sender:self];
}
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
FinalViewController *controller = segue.destinationViewController;
}
You can either store the selected indexPath in a property, or use
[[self.collectionView indexPathsForSelectedItems] firstObject]
to retrieve the selected cell. Once you have the cell you can access its imageView property, and pass its image to the FinalViewController (remember to create a public property on it).

How to get the selected section in a UITableView

I have a HistoryTableViewController with 2 sections hooked up to a detail view controller. I want to be able to display the text and subtitle text from the HistoryTableViewController in the details view, but I want to make sure that it detects the right section. I know somewhere along the line I'll have this:
if (section == 0)
{
labelCellNum.text = Whatever was the main text in the selected table view cell
labelDueDate.text = Whatever was in the subtitle text in the selected table view cell
}
else if (section == 1)
{
labelCellNum.text = Whatever was the main text in the selected table view cell
labelDueDate.text = Whatever was in the subtitle text in the selected table view cell
}
Since I'm displaying this on a details view controller, I don't know how to get the section from the TableViewController I'm getting displayed from. I pretty much need to know how to get the section, and the main text + subtitle text.
OK Perhaps I wasn't clear enough. This code is going in my ViewDidLoad of my DetailsViewController. NOT in my tableviewcontroller.
Here is the HistoryTableviewController code:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// HistoryDetailsViewController *HDV = [self.storyboard instantiateViewControllerWithIdentifier:#"HistoryDetails"];
// [self.navigationController pushViewController:HDV animated:YES];
NSLog(#"index path section--%i",[indexPath section]);
[self performSegueWithIdentifier:#"Push" sender:indexPath];
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if ([[segue identifier] isEqualToString:#"Push"]) {
HistoryDetailsViewController *detailVC=(HistoryDetailsViewController*)segue.destinationViewController;
detailVC.labelCellNum.text = #"Cell test";
detailVC.labelDueDate.text = #"Date Test";
}
}
And below is the code of my detailsViewController:
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
labelCellNum.text = #"This isnt even getting called.";
}
check this , its simple
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
NSLog(#"index path section--%i",[indexPath section]);
[self performSegueWithIdentifier:#"Push" sender:indexPath];
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if ([[segue identifier] isEqualToString:#"Push"]) {
DetailViewController *detailVC=(DetailViewController*)segue.destinationViewController;
detailVC.title=#"value to pass";
}
}
There you go!
#pragma mark - UITableViewDelegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// Selected item infos
//
int section = indexPath.section;
int row = indexPath.row;
NSLog(#"section: %d / row: %d", section, row);
}
I assume you have a segue from the HistoryVC to the details VC. So you can pass the data across to the details VC in the prepareForSegue method in the HistoryVC. In the code fragment below, I am passing the cell title over into the new VC to set it's title. You could set other properties in the target VC, to suit your needs.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// get selected row's cell
//
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
// set desitination VC title
//
UIViewController *vc = [segue destinationViewController];
vc.navigationItem.title = cell.textLabel.text;
}

One TableViewController with 2 sections linking to 1 DetailView?

So In my project I have one HistoryTableViewController which contains 2 sections. One section is the PeopleYouOwe and the other section is a group of PeopleWhoOweYou. How would I be able to hook up this one tableviewcontroller and link it to a detail view that will display different data according to my sections?
Try below approach using prepareForSegue -
creat tableView outlet named myTableView
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
NSIndexPath *path = [self.myTableView indexPathForSelectedRow];
if (path.section == 0)
{
if ([segue.identifier isEqualToString:#"PeopleYouOwe"])
{
PeopleYouOwe *peopleYouOweVC = segue.destinationViewController;
// you can get data of cell as array[path.row]
}
}
else if (path.section == 1)
{
if ([segue.identifier isEqualToString:#"PeopleWhoOweYou"])
{
PeopleWhoOweYou *peopleWhoOweYou = segue.destinationViewController;
// you can get data of cell as array[path.row]
}
}
}
You use the delegate methods provided with UITableViews like this:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSInteger row = indexPath.row;
NSInteger section = indexPath.section;
if(section == 0) // example
{
// do whatever
}
else if (section == 1)
{
// do something else
}
}
If this is not what you're looking for you will need to provide more details and ideally some code to show what you already have. Your question is vague.
If you prefer prepareForSegue, you can use something like:
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
then take action based on section and row.

Retrieving UITableViewCell Label Values For Passing To Modal Edit View

I am trying to pass existing attribute values for a managed object, to a modal segue view for editing. From "editing mode," I'm going from a UITableViewController subclass (BreadRackTableViewController), using a modal segue to a UIViewController subclass (EditBreadRackTableViewController) by means of an embedded UINavigationController. Normal TableViewCell selection pushes to another UITableViewController subclass, but that's not important for the time being.
I've added properties to my editing view controller header (and #synthesized), to function as getters:
#property (nonatomic, strong) id existingBreadRackDataName;
#property (nonatomic, strong) id existingBreadRackDataDetails;
What I'm trying to do is populate the edit view's fields with the existing Core Data Entity Attributes, which would have been previously set by the user (in theory). I can get the data to show up if I pass along a literal string value, but I need to retrieve and pass the existing data.
Here's what I have currently:
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"editBreadRackSegue"])
{
EditBreadRackTableViewController *ebrtvc = (EditBreadRackTableViewController *)[segue destinationViewController];
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
BreadRackClass *breadRackClass = [[self fetchedResultsController]objectAtIndexPath:indexPath];
// [ebrtvc setBreadRackClass:breadRackClass];
ebrtvc.existingBreadRackDataName = breadRackClass.breadRackDataName;
ebrtvc.existingBreadRackDataDetails = [breadRackClass valueForKey:#"breadRackDataDetails"];
}
}
These last two lines of code...
ebrtvc.existingBreadRackDataName = breadRackClass.breadRackDataName;
ebrtvc.existingBreadRackDataDetails = [breadRackClass valueForKey:#"breadRackDataDetails"];
...they both return nil. If I specify a literal string though, that literal string shows up where it needs to.
All of that said, my question is:
How do I retrieve the attribute's key value for that selected row (or just the textLabel and detailTextLabels), and assign it to my setter?
Solution:
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"editBreadRackSegue"])
{
NSIndexPath *indexPath = [self.tableView indexPathForCell:sender];
BreadRackClass *breadRackClass = [[self fetchedResultsController]objectAtIndexPath:indexPath];
[segue.destinationViewController setExistingBreadRackDataName:[breadRackClass valueForKey:#"breadRackDataName"]];
[segue.destinationViewController setExistingBreadRackDataDetails:[breadRackClass valueForKey:#"breadRackDataDetails"]];
}
// code for other segues here...
}
I ended up removing the ebrtv variable, and cleaned up the code a little bit. What worked though, was using the indexPathForCell:sender instead of indexPathForSelectedRow when declaring my indexPath for breadRackClass.
I think the indexPathForSelectedRow could be a problem.
You can just pass the indexPath from the didSelectRowAtIndexPath to the prepareForSegue , like:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[self performSegueWithIdentifier:#"editBreadRackSegue" sender:indexPath];
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"editBreadRackSegue"])
{
NSIndexPath *clickedIndexPath = (NSIndexPath*)sender;
if( [clickedIndexPath isKindOfClass:[NSIndexPath class]] ){
BreadRackClass *breadRackClass = [[self fetchedResultsController]objectAtIndexPath:clickedIndexPath];
EditBreadRackTableViewController *ebrtvc = (EditBreadRackTableViewController *)[segue destinationViewController];
ebrtvc.existingBreadRackDataName = breadRackClass.breadRackDataName;
ebrtvc.existingBreadRackDataDetails = [breadRackClass valueForKey:#"breadRackDataDetails"];
}
}
}
Let me know if it works for you.