Indexpath.row value not updating - iphone

in iphone application.
I'm trying to get indexPath.row value (out of didselectedrowatindexpath method) to do something on the basis of row selected in programmatically created tableview.
i need to access indexpath.row out of didselectedrowatindexpath method where if/else will define the action on the basis of indexpath.row.
there are 7 cards images in application and one [menu list]table view. whenever user will click on row of table view,then need to touch the image
I'm trying this code to get the IndexPath.row value. The problem is indexPath.row value is not updating everytime. It's just taking the old value. Please sugggest how to solve this issue.
- (void)touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event
{
NSUInteger nSection =[myTableView numberOfSections]-1 ;
NSUInteger nRow = [myTableView numberOfRowsInSection:nSection];
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:nRow inSection:nSection];
NSLog(#"No of sections in my table view %d",nSection);
NSLog(#"No of rows in my table view %d",nRow);
NSLog(#"Value of selected indexPath Row %d", [indexPath.row]);
NSLog(#"VAlue of Array arrOperationChk %d",[arrOperationChk count]);
}

This code appears to respond to something (the table?) being touched. You then ask the table how many rows it has in its last section and create an indexpath to that.
The table caches the number of rows in each section. If you have changed the number of rows, you need to tell the table, either by calling -insert/deleteRowsAtIndexPaths:withRowAnimation:, or by calling -reloadData. Otherwise the table has no way to know that it needs to re-query its datasource (which you provide).

Unless I'm reading this code wrong, aren't you just getting the index path to the last cell+1 of the last section? I wouldn't expect that to change.
If you want to get the selected cell, use the
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
method in your UITableViewController object.

As other people have said, there's nothing in your code that would change the indexPath variable you've just created.
Also, the syntax [indexPath.row] looks wrong - you don't need the square brackets there unless you're calling a method. When you use the dot syntax like that on a pointer in Objective-C, you don't think of it as a method call (even though there is one, implicitly), but rather as a pseudo-instance variable as of a struct.
What is your big picture goal? If we understood what you are trying to achieve / what is the desired behavior, maybe a more useful answer will arise.

Related

Getting access to a UITableViewCell row that is currently not showing

Is there a way to get access to a UITableViewCell that is not currently on screen? I'm trying to update rows that are currently not in view. I am using this collapsable/expandable rows for a UITableView in one of Apple's example codes. I use this:
for (NSInteger row = 0; row < totalRows; row++) {
NSIndexPath *path = [NSIndexPath indexPathForRow:row inSection:section];
OrderTableViewCell *cell = (OrderTableViewCell *)[_tableView cellForRowAtIndexPath:path];
cell.CheckmarkButton.selected = YES;
cell.Symbol.isSelected = YES;
}
My totalRows is correct in that I get the number of rows from the TableView. So I thought I could use that, loop through all the rows, and set some values. However, if I check the state of the rows, the ones that are currently on screen have values and I can change them, but the ones off screen are null and cannot be set. Is there a way I can get around this? Thanks.
Depending on what you want to update you could just update the ith entry in a backing collection.
For example you could have a collection that stores bools corresponding to CheckmarkButton selected. In your loop you could set myArray[row] = YES. In cellForRowAtIndexPath you can do cell.CheckmarkButton.selected = myArray[indexPath.row].
If you want to maintain multiple items for each cell then myArray in the above example could contain instances of an object that holds values relevant to the ith cell.
Well why do you have to update a cell like that... If the cell is out of view, to save memory the system unloads it, and since its not in the view there is no need for you to update the cell directly, rather you should have the state be reflected in such way that when cellForRowIndexPath is called by the table view to load the cell the desired look is shown... The only reason youd want to do what you are doing is if the cell is showing and you need to update the cell, for the user... Even then you can still set your state and call the reloadRowsAtIndexPaths instead of manipulating the cell directly... Hope that helps

Delete Row from UITableView Outside TableView Delegate

I am trying to delete a row from UITableview outside the delegate method. I am calling a method when I click a button inside a table cell and trying to delete the row inside that method.
Here is the function I am using
UIButton *btn = (UIButton*)sender;
int tag = btn.tag;
UITableViewCell *buttonCell = (UITableViewCell*)[[btn superview] superview];
NSIndexPath *indexPath = [self.msgTbl indexPathForCell:buttonCell];
[deleg.rmessages removeObjectAtIndex:buttonRow];
[self.msgTbl deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationTop];NSInteger buttonRow = indexPath.row;
[self.msgTbl reloadData];
Using this one or two rows get deleted but after that its crashing giving exception
Number of rows before and after deletion must be same
How can I do this in ios?
Thanks
Your problem is that the data that is being taken to populate your table isn't consistent with the table after deleting the cell. Make sure your dataSource methods provide the correct data after doing this (for example, if it is an array of objects you are using to populate the table, you must remove the object from the array as well)
The root issue is that this method:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;
Must return the correct number of rows, and it isn't. When you remove the item from deleg.rmessages, is this the same object that is being used to supply the return value of the above method? (Something like [deleg.rmessages count]?)
Also, in my experience that exception often gives you more details, in particular:
How many items it had before
How many were added/deleted
How many it expects to have vs. how many it does have after the reload
Do you see anything like this being mentioned? If so, it would be worth including in your question.
Sidenote:
It's a bad idea to rely on:
UITableViewCell *buttonCell = (UITableViewCell*)[[btn superview] superview];
To return the UITableViewCell. You appear to assign the tag of the button to a local variable, but never use it. (Maybe this would be a good place to store the index of the UITableViewCell, and then subclass the cell to maintain an ivar to the button?) This is only part of the problem.

How to make dynamically adding of rows when user reached to the last row of the UITableView?

I have a UITableview which shows 10 rows currently which is fixed static. Now I want to add a feature into it. I want to add a more 10 rows to the table when user reach to the last row of the UITableView. I mean currently I am showing fixed 10 rows in the application.
But now I want to add 10 more rows whenever user reaches to the last row of previous UITableview.
Please give me any suggestions or any sample code to achieve my motive. Thanks in advance.
It is actually quite simple. What you need to do is implement the tableView:willDisplayCell:forRowAtIndexPath: method, which belongs to the UITableViewDelegate protocol. This method hits every time a cell is about to be displayed. So, it will let you know when the last cell is about to be displayed. Then you could do something like-
– (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *) cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
if(indexPath.row == [self.array count] - 1) //self.array is the array of items you are displaying
{
//If it is the last cell, Add items to your array here & update the table view
}
}
Another (a bit mathematical) option is to implement UIScrollView delegate methods (UITableView is a subclass of UIScrollView), namely scrollViewDidEndScrollingAnimation: or scrollViewDidScroll:. These will let you know the y-position of the content the user is viewing. If it is found that the bottom most content is visible, you can add more items.
HTH,
Akshay
uitableview is derived from uiscrollview. To achieve your objective, you need to implement scrollViewDidEndDecelerating:
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
float endScrolling = scrollView.contentOffset.y + scrollView.frame.size.height;
if (endScrolling >= scrollView.contentSize.height)
{
// your code goes here
}
}
This will detect a "bouncing effect" like shifting up the visible rows to indicate that one would like to see more.
How would you exactly want to invoke the loading of the additional 10 rows? When a user just scrolls down to see the first 10 that are loaded by default he might not want to load 10 more already.
You may add a "add more" line as the last row of your table. When the user clicks on this one you add 10 more.
(I don't know how one would detect a "bouncing effect" like shifting up the visible rows to indicate that one would like to see more.)
The basic logic would look like this:
in cellForRowAtIndexPath you check if the user clicked on the last line and then invoke your code to add the 10
to actually add 10 more lines you have to call [myTable reloadData]
but before you call you need to increase the returned value of numberOfRowsInSection by 10 and make sure that cellForRowAtIndexPath will correctly return your new lines 11-20
ps if you REALLY want 10 additional rows to be loaded when the user reaches the end of the table you need to invoke the loading of 10 more in cellForRowAtIndexPath or willDisplayCell:forRowAtIndexPath: when it is called for your last line.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [categoriesList count];
}
Here categoriesList is an array. We can add objects to this array and call reloadData in the tableview.

How to add data in UITableview at run time?

I want to add data or cells in UITableview when we scrolled to the last cell of the UITableView. In other words, as we have seen in many iPhone apps, that when we reached to the last cell of the UITableview the more cells get added to it at runtime. I want to achieve that functionality in my project.
Means Add some more cells to the UITableview when we reached to the previously added last cell.
Please tell me the sample code or any tutorial for it.
I think that there are 2 questions here.
First, how to detect the end of tableVeiw? Second, how to add cells dynamically?
First question, I think it can be done by observing the value of content offset of scrollView or current indexPath of tableView cell. The content offset of scrollView can be observed by following method of UIScrollViewDelegate. The content offset is a property of scrollView.
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
CGFloat currentOffset = scrollView.contentOffset;
// Detect scrolling to bottom by this offset value.
....
}
The index of cell may be decided by the method of UITableViewDataSource.
- (UITableViewCell *)cellForRowAtIndexPath:(NSIndexPath *)indexPath
Second question can be overwhelmed by the methods of UITableView.
beginUpdates
endUpdates
insertRowsAtIndexPaths:withRowAnimation:
deleteRowsAtIndexPaths:withRowAnimation:
insertSections:withRowAnimation:
deleteSections:withRowAnimation:
I remember the sample codes in this official document will teach how to use above methods. They don't reload all cells, but careless operations will result in crash easily.
If you have data stored in an array, then you would definitely have the count of how many cells you want.
Use the below code for your help
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{ return [array count];}
i believe this would have helped you.
Populate the tableView by using an array (as you should always do). When the delegate method cellForRowAtIndexPath ask your for the last cell, repopulate your array with new (more) data and make a [tableView reloadData].
you just want to add data in table?
Then, first you may need to add one more view, modal view. You should write some specification about what you want to add in this view.
Next you send a message to existing data array(Assume you use array)
[ExistingArrayData addObject:TemporalilyNewObject];
And you can sort the data by using NSSortDescriptor.
NSSortDescriptor *nameSorter = [[NSSortDescriptor alloc] initWithKey:KEY_VALUE ascending:YES selector:#selector(caseInsensitiveCompare:)];
[ExistingArrayData sortUsingDescriptors:[NSArray arrayWithObject:nameSorter]];
In this case, this method sorts the data by KEY_VALUE, ascending.
Finally, you shoule add this code in RootView's viewWillAppear method.
[self.tableView reloadData];
This code notifies app of change of data.
-(void) tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath{
int i=0;
i=indexPath.row;
int count=[urTablearray count];
if (count == (++i)) {
//do ur stuff here
here add object to urTablearray
[urTablearray addObject:#"vijay"];
}
}
Note: urTablearray is NSMutableArray type not NSArray

Add blank cell at end of UITable

I'm trying to add an additional cell for custom content as the last cell in a tableView, without altering the dictionary that creates the other content of the table. I think the place to add it is in cellForRowAtIndexPath rather than adding one to the numberOfRowsInSection, which just crashes if I do.
I get a cellCount from the dictionary that creates the data for the table, then in cellForRowAtIndexPath, I have:
if (indexPath.row == cellCount) {
... stuff goes here
return cell;
}
of course, this never gets called. If I do if (indexPath.row == cellCount -1) it overwrites the last cell with content.
I can get this to work if I add a blank entry into the xml from which I am populating the dictionary, but that's ugly.
Example code would be neat!
The problem here is that tableviews are designed to easily and accurately display the contents of you data-model and you've decided you don't want to do that. You're fighting the API.
The straight forward way to do this would be to put a check in numberOfRowsInSection such that it adds one to the row count when you want to display the input row. Then in cellForRowAtIndexPath: you will need to check if the table view is asking for the input row and return the appropriate type of cell.
From a UI design point, you might want to consider whether this setup is the best. This isn't a standard setup. Is the user going to understand that they can only edit the last row of the table? Will they understand they can't edit the other rows? Does anything in the UI tell them how all this works? Does the user have to scroll to the end of the table every time they want to add data? How long can this table grow? How will displaying a keyboard for the last row of the table affect how table scrolls?
I think it would be a better design to use a footer view to display the text field such that is is visually distinct from the rest of the table. It would be programmatically simpler as well. You wouldn't have to check if the table was asking for the last row every single time it ask for a cell.
Edit:
In thinking about it, perhaps a sectioned table would be simpler. Just put the special row in its own section (with or without a header.) That would simplify you handling of the rows that source from the dictionary because the row count in that section would always be the count of the dictionary. Likewise, you could just check the section attribute of the indexpath to know what cell to return for what row.
First you need to modify the numberOfRowsInSection to return +1. Then in cellForRowAtIndexPath you need to add that extra blank cell.
You need to provide for the extra cell in both cellForRowAtIndexPath and numberOfRowsInSection.
Assuming that cellCount is the actual number of cells in your array then: (a) in cellForRowAtIndexPath return the extra custom cell when indexPath.row == cellCount, and (b) in numberOfRowsInSection you need to return cellCount+1.
Assuming a single section, an example would go something like this:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [journalArray count] + 1; // add 1 for summary
}
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.row < [journalArray count]) {
return [journalArray objectAtIndex:indexPath.row];
} else {
return summaryCell;
}
}