Why NSIndexPath length always show 2? - ios

I have created a NSIndexPath object but when I print the value of its length property it will always show the value as 2.
NSIndexPath *index = [NSIndexPath indexPathForItem:0 inSection:4];
{length = 2, path = 4 - 0}
Why length is always 2?

Because the index path is made of two indexes - the section and the item number.

basically NSIndexPath is combination of Section and Row, so it will show length as 2.

Related

How Can I Get The indexpath and row in XCODE 5

I have an app that used to work before I upgraded to XCODE 5. I needed to find the row that was selected for a structure I was displaying which has over 100 rows so obviously can be scrolled on the display. The code that used to work is:
NSIndexPath *indexPath = [self.mainTableView indexPathForCell:myCell];
NSInteger row = [indexPath row];
Now, regardless of the row selected, the value of row is always 0. Anyone have any suggestions for me? Thanks.
This worked for me...
CGPoint pos = [pressedButton convertPoint:CGPointZero toView:self.mainTableView];
NSIndexPath *indexPath = [self.mainTableView indexPathForRowAtPoint:pos];
NSInteger row = [indexPath row];
Remember that in Objective-C, you can always send a message nil, and methods that return something (i.e., not void) will return either nil(for an object) or 0 (for a value) when sent to nil (for structs, it is more complicated; read this).
So make sure that:
self.mainTableView is not nil
indexPath is not nil

Crash with tableView endUpdates using RATreeView

I'm using the RATreeView component at https://github.com/Augustyniak/RATreeView by RafaƂ Augustyniak.
Using the posted /Demo code on github:
Add:
RADataObject *rdo = [self.data objectAtIndex:0];
[self.treeView expandRowForItem:[rdo.children objectAtIndex:0]];
at the bottom of viewWillAppear.
Change the lines of the phone objects to:
(void)loadData
{
RADataObject *phone2 = [RADataObject dataObjectWithName:#"Phone 2" children:nil];
RADataObject *phone3 = [RADataObject dataObjectWithName:#"Phone 3" children:nil];
RADataObject *phone4 = [RADataObject dataObjectWithName:#"Phone 4" children:nil];
RADataObject *phone1 = [RADataObject dataObjectWithName:#"Phone 1" children:[NSArray arrayWithObjects:phone2, phone3, phone4, nil]];
RADataObject *phone = [RADataObject dataObjectWithName:#"Phones"
children:[NSArray arrayWithObjects:phone1, nil]];
(This gives a nested list, where phone -> phone 1 -> phone2, phone3, phone4)
This reproduces the crash that I am having in my app.
It crashes on:
(void)expandCellForTreeNode:(RATreeNode *)treeNode withRowAnimation:(RATreeViewRowAnimation)rowAnimation
with an EXC_BAD_ACCESS for:
[self.tableView endUpdates];
I've traced through this for a couple of days, and am not sure how to work around this crash (or even why it is happening).
The error message I get using your code is the following. To reproduce this error, move
[self.treeView expandRowForItem:[rdo.children objectAtIndex:0]];
to viewDidAppear.
Terminating app due to uncaught exception
'NSInternalInconsistencyException', reason: 'Invalid update: invalid
number of rows in section 0. The number of rows contained in an
existing section after the update (24) must be equal to the number of
rows contained in that section before the update (12), plus or minus
the number of rows inserted or deleted from that section (24 inserted,
0 deleted) and plus or minus the number of rows moved into or out of
that section (0 moved in, 0 moved out).'
The number of rows has changed to 24, copying existing rows and insert them to the table, but the insertion is not successful.
It seems the thing you want to do is to expand a sub node, you can do that by looking at the implementation of didSelectRowAtIndexPath delegate method, because expanding a row is just like clicking a row. To do it manually add the following code.
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0];
RATreeNode *treeNode = [self.treeView treeNodeForIndexPath:indexPath];
[self.treeView expandCellForTreeNode:treeNode];
NSIndexPath *indexPath1 = [NSIndexPath indexPathForRow:1 inSection:0];
RATreeNode *treeNode1 = [self.treeView treeNodeForIndexPath:indexPath1];
[self.treeView expandCellForTreeNode:treeNode1];
It is just as if you click row 0, and row 1 sequentially. You also need to import this header file.
#import "RATreeView+Private.h"

Get number of rows in UICollectionView

UICollection view automatically adjusts the number of rows based on the number of items per section and size of each cell.
So is there a way to get the number of rows in an UICollectionView?
For example: If I have a calendar with 31 days that automatically fit into n rows.
How do I get the value of this 'n' ?
You can get the position of an item after it's laid out with [myCollectionView.collectionViewLayout layoutAttributesForItemAtIndexPath:]
If you don't know the dimensions of your items, or don't want to assume that you do, one approach would be to iterate over the items in your collection and look for a step change in the Y-position of the item. Obviously this only works if you're using a grid-based layout.
This does the trick:
NSInteger totalItems = [myCollectionView numberOfItemsInSection:0];
// How many items are there per row?
NSInteger currItem;
CGFloat currRowOriginY = CGFLOAT_MAX;
for (currItem = 0; currItem < totalItems; currItem++) {
UICollectionViewLayoutAttributes *attributes =
[collectionView.collectionViewLayout layoutAttributesForItemAtIndexPath:
[NSIndexPath indexPathForItem:currItem inSection:0]];
if (currItem == 0) {
currRowOriginY = attributes.frame.origin.y;
continue;
}
if (attributes.frame.origin.y > currRowOriginY + 5.0f) {
break;
}
}
NSLog(#"new row started at item %ld", (long)currItem);
NSInteger totalRows = totalItems / currItem;
NSLog(#"%ld rows", (long)totalRows);
If you do know the dimensions of your items, you could get the position of the last item with
NSInteger totalItems = [self.timelineCollectionView numberOfItemsInSection:0];
NSIndexPath lastIndex = [NSIndexPath indexPathForItem:totalItems - 1 inSection:0];
UICollectionViewLayoutAttributes *attributes =
[myCollectionView.collectionViewLayout layoutAttributesForItemAtIndexPath:lastIndex];
// Frame of last item is now in attributes.frame
Then take that last item's dimensions and divide by your known row height. Don't forget to account for any headers or spacing. These properties are also available from the UICollectionViewFlowLayout.
Pull the flow layout out with
UICollectionViewFlowLayout *myFlowLayout = (UICollectionViewFlowLayout*)myCollectionView.collectionViewFlowLayout;
And look in
myFlowLayout.headerReferenceSize
myFlowLayout.minimumLineSpacing
and so on.

How to change uitableviewcell data in different section?

I want to change the data of two rows in two different sections when one of them is selected so that they will have the same answer. But it is not working:
NSIndexPath *indexPath1 = [NSIndexPath indexPathForRow:row1 inSection:section1];
cell = [self.tableView cellForRowAtIndexPath:indexPath1];
//DO SOMETHING WITH CELL LABEL
NSIndexPath *indexPath2 = [NSIndexPath indexPathForRow:row2 inSection:section2];
cell = [self.tableView cellForRowAtIndexPath:indexPath2];
//MAKE THIS CELL LABEL SAME AS THE LAST ONE
It doesn't work if the second cell is in a different section! Any suggestion?
You will get a nil from cellForRowAtIndexPath: if one of the cells isn't visible at the moment.
You should therefore get the needed entry from your data-model, not from the UI.
Change the needed information there:
NSArray *section1Data = [self.dataModell objectAtIndex:section1];
NSDictionary *dataObject1 = [section1Data objectAtIndex:row1];
[dataObject1 setValue:#"My new Text." forKey:#"theTextPropertyKey"];
NSArray *section2Data = [self.dataModell objectAtIndex:section2];
NSDictionary *dataObject2 = [section1Data objectAtIndex:row2];
[dataObject2 setValue:#"My new Text." forKey:#"theTextPropertyKey"];
Then reload the needed cells in the UI:
NSArray *indexPaths = #[indexPath1, indexPath2];
[self.tableView reloadRowsAtIndexPaths:indexPaths];

nsindexpath access to row to section property causes SIGABRT?

Targeting iOS 5.0 I see SIGABRT when I try to access row or section properties of NSIndexPath object in the following code:
NSIndexPath* path = [[NSIndexPath alloc] initWithIndex:0];
int row = path.row; //SIGABRT
int section = path.section;//SIGABRT
This example suggests using indexPathWithIndex: instead http://developer.apple.com/library/mac/#samplecode/SourceView/Listings/BaseNode_m.html#//apple_ref/doc/uid/DTS10004441-BaseNode_m-DontLinkElementID_6
path = [NSIndexPath indexPathWithIndex:0];
The results remain consistent. Does anyone have an explanation of why this might happen? Is it that we just cannot operate on NSIndexPath in iOS 5.0?
Thanks in advanced.
Try creating the index path using indexPathForRow:inSection:
NSIndexPath* path = [NSIndexPath indexPathForRow:0 inSection:0];
The only thing I can think of is to make sure you have UIKit.framework as one of your frameworks. You can do this by pressing the plus button in the "Link Binary With Libraries" section under "Build Phases" on your target. Also, make sure that you import NSIndexPath.h in the file you're trying to access the index path from.
I've run into this problem before, and this solved it. That's because although NSIndexPath is universal between Cocoa and CocoaTouch, the Cocoa version doesn't have properties row and section.
If you already have UIKit.framework, try using [NSIndexPath indexPathForRow:row inSection:section] instead of [NSIndexPath indexPathWithIndex:index].
I think the problem is that indexPathWithIndex: creates a one-node index path. Same for initWithIndex:. The section and row properties come from the UITableView category to the NSIndexPath class. A one-node index path is invalid for use with a table view because index paths passed to table views must contain two indices specifying the section and row (according to the error message I get when I run your code). The following code creates an index path with two indices and runs without throwing an NSInternalInconsistencyException:
NSUInteger x[] = {0 , 0};
NSIndexPath *path = [[NSIndexPath alloc] initWithIndexes: x length: 2];
int row = [path row];
int section = [path section];
row = path.row;
section = path.section;
Is this what you meant by "operate on NSIndexPath in iOS 5.0"?

Resources