9

I'm filling a TableView with CoreData.

Until now I was doing something like this:

        NSManagedObject *managedObject = [self.fetchedResultsController objectAtIndexPath:indexPath];

...to retrieve the object to fill the row.

Everything was working fine until I realized I have to manage the first row of the table as an exception because the first line will contain other content, not provided by CoreData.

Now my issue is how can I manipulate the indexPath to shift everything by one. I would like to do something like this:

// I know this is not going to work, just to give you an idea...
   NSManagedObject *managedObject = [self.fetchedResultsController objectAtIndexPath:indexPath-1];

but I cannot find the right syntax to manipulate the indexPath. Can anyone help me? Thx for your time!

Sr.Richie
  • 5,680
  • 5
  • 38
  • 62

2 Answers2

13

In case we are talking about iOS UITableView index path there's much easier way:

NSIndexPath* newIndexPath = [NSIndexPath indexPathForRow:oldIndexPath.row+1 inSection:oldIndexPath.section];

Cheers... :)

Ariel
  • 2,430
  • 1
  • 17
  • 20
  • I had to use row-1 to get previous row indexPath, which is how I read the question. But +1 anyhow cause this is basically what I needed. – Kai Qing Jul 25 '12 at 01:58
2

If you're talking about a standard iOS UITableView, then your index path is an instance of NSIndexPath, and will have two entries: a section index and a row index. If I understand you right, you want to decrement the row index by 1 every time you go to fill a table view cell. (I'm assuming you only have one section, or don't care about the section index - if this is wrong, please edit your question.)

Basically what you need to do is construct a new NSIndexPath instance with your adjusted indices, then use that to query your fetched results controller. Something like this would work (untested):

NSUInteger indexes[2];
[indexPath getIndexes:indexes];
indexes[1]--;
NSIndexPath * adjustedIndexPath = [[NSIndexPath alloc] initWithIndexes:indexes
                                                                length:2];
NSManagedObject * managedObject = [self.fetchedResultsController
                                    objectAtIndexPath:adjustedIndexPath];

This basically does the following:

  1. Pulls the existing indexes into a C array of NSUIntegers
  2. Decrements the last index (at position 1 - the row index) by 1
  3. Creates a new NSIndexPath with the adjusted indexes from the C array
  4. Fetches the managed object using the new index path

Note again that this doesn't touch the section index at all, and so will adjust every cell in your table, regardless of whether it's in your first section. If that's not what you want, either wrap the adjustment in a conditional (e.g. if([indexPath indexAtPosition:0] == 0)) or add your own custom logic.

Tim
  • 59,527
  • 19
  • 156
  • 165
  • In case we are talking about UITableView index path there's much easier way: NSIndexPath* newIndexPath = [NSIndexPath indexPathForRow:oldIndexPath.row+1 inSection:oldIndexPath.section]; Cheers... :) – Ariel Nov 22 '11 at 19:26
  • 1
    @Ariel: ...right. Definitely was looking at the Mac class reference and not iOS. Well done, and if you want to post it as a separate answer, I'd recommend it over mine :) – Tim Nov 22 '11 at 19:35
  • I posted it thought from the question there's no way to know if answer needed for macOS or iOS. Let there be both of the answers for generic purposes :) – Ariel Nov 22 '11 at 19:47
  • As you supposed, I just have one section in my TableView. I'm trying to implement @Ariel answer (as Tim suggested too) but something weird is happening. When I first visualize the table, the contents are finally right, that means that from the second row on the the contents of the cell are what I'm expecting after this tweak. But when I scroll down the table, the app crashes [[UITableViewCell categoryNameLabel]: unrecognized selector sent to instance 0x8146560]. – Sr.Richie Nov 22 '11 at 19:47
  • @Ariel is iOS, sorry for the confusion, I supposed that the tag iPhone was enough clear :( – Sr.Richie Nov 22 '11 at 19:49
  • @Sr.Richie: that almost sounds like a separate issue - it results from you calling the `categoryNameLabel` method on a table cell instance. I'd suggest asking a separate followup question (linking to this one), posting the code where you call `categoryNameLabel`, and getting help there. – Tim Nov 22 '11 at 19:52
  • Oh, sorry... Haven't put my attention on tags. About crash, it seems that you are calling for categoryNameLabel method on UITableViewCell object. You need to check your memory management. – Ariel Nov 22 '11 at 19:53
  • Right now I have a doubt, sorry but I'm a n00b in Objective-C development so this could sound weird: the indexPath value is relative to the absolute position of the row in the table or to the relative position of the row in the screen? This means: indexPath.row = 1 is only happening at the first row of the table or every row at the the top of the view has indexPath = 1?? Sorry but I'm starting to get confused – Sr.Richie Nov 22 '11 at 19:58
  • Hm... you see, the UITableView may present data in sections (take it as nested array of data with depth of 1 or maybe a little-bit simpler example is array of arrays). Every section may contain a number of rows, so it is possible that you'll have more than one cell with row index 1, they just will be in different sections. It doesn't have any connection with visibility index as there's no such one. – Ariel Nov 22 '11 at 20:16
  • @Ariel thx for the explication, it was a stupid question probably but I was trying to understand why the app was crashing. And by the way, the problem was the identifier/reuseIdentifier that was the same for the first row (the exception) and the "standard" rows. The app was dequeuing the cells without considering that they were different classes. Thx for your help! – Sr.Richie Nov 23 '11 at 11:24