Getting row number in scrollViewDidEndDecelerating - iphone

when i use
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView{
NSArray *visibleCells = [my_table visibleCells];
i want to know the number of the row (in my_table) that is visible (with visibleCells).
For example, if i do
[visibleCells count];
i know that there are 5 rows visible, but i need to know the real number (for example: number 3, 4, 5, 6, 7 in the table view).
Is it possible?

You can call indexPathForCell: on the table view with the first and last objects of the array to get the two index paths.

solved!
using this
UITableViewCell *currentCell = [visibleCells objectAtIndex:i];
NSIndexPath *indexPath = [tabella_gallery indexPathForCell:currentCell];
works fine!

Here is a method I use
func loadImagesForVisibleRows() {
// Get the visible cells indexPaths
let indexes: Array = tableView.indexPathsForVisibleRows()!
// Loop through them to determine whether visible or not
for index in indexes {
let row = index.row
// Do what you need to do
}
}

Related

TableViewCell's textLabel value returns to 1 when cell is scrolled out of the view

i have a table view in which i can add 1 or subtract 1 to the value of my cell.textLabel.text but when i switch views and return or scroll a cell out of the view, and when it comes back into view, the textLabel's value returns to 1 which is the original starting point! Please help! Here is the code to add and subtract 1:
- (IBAction)addLabelText:(id)sender{
cell = (UITableViewCell*)[sender superview]; // <-- ADD THIS LINE
cell.textLabel.text = [NSString stringWithFormat:#"%d",[cell.textLabel.text
intValue] +1];
}
- (IBAction)subtractLabelText:(id)sender
{
cell = (UITableViewCell *)[sender superview];
if ( [[cell.textLabel text] intValue] == 0){
cell.textLabel.text = [NSString stringWithFormat:#"%d",[cell.textLabel.text intValue] +0];
}
else{
cell.textLabel.text = [NSString stringWithFormat:#"%d",[cell.textLabel.text intValue] -1];
}
}
This is happening because, the cells will be re-used on scrolling. The table view's datasource method will be invoked, hence the values get reset to the original value. You can maintain an array of NSNumbers as a datasource to the tableview (is, in cellForRowAtIndexpath: , set the text fo the cell label from the array). Each time you need to add or subtract, do it the corresponding NSNumber obj and re-load the tableview.
Seems like you are allocating a new cell each time.. and not using the cell re-usablility method.
In your case, when you are performing arithmetic actions to your previous values and you don't have an array to store previous values. The easiest way to fix this is make your Cell-Identifier unique. (something like #"Cell-%d",indexPAth.row)
Note: However, more efficient way would be to save your result in the array you are populating your data from, without making you Cell-Identifier unique.
You are not updating your data modal. That is why it is taking the original content value.
After change the cell text value reload the tableview [self.tableview reloadData]

cellForRowAtIndexPath inserting in array

I'm getting a weird issue. I have a custom UITableViewCell and each cell has a UIButton and UITextField. When the button is clicked, it changes the textfield value to some constant.
Now in the cellForRowAtIndexPath method I have this:
folderTitleTextView.tag=indexPath.row;
[arrayOfTextFields insertObject:folderTitleTextView atIndex:indexPath.row];
NSLog(#"indexpath.row:%i", indexPath.row);
NSLog(#"text fields count %i", [arrayOfTextFields count]);
So if I have two cells, then every time I reload the table, it adds two more objects to the arrayofTextFields, even though it should replace the existing ones. So if I have two cells and I reload the table 3 times, then for some reason arrayOfTextFields count is 8.
This folderTitleTextView.tag=indexPath.row; is not a good idea because everything starts with a tag of 0, so when accessing views with viewWithTag:0 or when setting up the row 0, you will get weird results.
I would suggest also checking the number of items in arrayOfTextFields and use [arrayOfTextFields replaceObjectAtIndex:indexPath.row withObject:folderTitleTextView]; or [arrayOfTextFields insertObject:folderTitleTextView atIndex:indexPath.row]; depending on the current count for arrayOfTextFields
Try this:
folderTitleTextView.tag = (indexPath.row + 100);
if ([arrayOfTextFields count] <= indexPath.row) {
[arrayOfTextFields insertObject:folderTitleTextView atIndex:indexPath.row];
} else {
[arrayOfTextFields replaceObjectAtIndex:indexPath.row withObject:folderTitleTextView];
}
NSLog(#"indexpath.row:%i", indexPath.row);
NSLog(#"text fields count %i", [arrayOfTextFields count]);
The question is what are you trying to do?
Right now you add the textView to an array each time a cell is displayed.
If you have 1 cell you have 1 textView in the array because cellForRowAtIndexPath: was called 1 time.
If you add another cell so you have 2 total cell cellForRowAtIndexPath will be called another 2 times and it will add 2 textViews to the array that already has one -> 3
If you add another cell cellForRowAtIndexPath adds 3 more textViews to the 3 that are already there -> 6
So much for the explanation of your results.
My suggestion is to get rid of that array and get rid of the tag, most likely those are not needed at all.
you can access the cell with something like this:
- (IBAction)buttonPressed:(UIButton *)sender {
UIView *contentView = [sender superview];
UITableViewCell *cell = (UITableViewCell *)[contentView superview];
// you should assign a tag to the textField of your cell. Use the same tag for each textView in all cells.
UITextField *textField = (UITextField *)[cell viewWithTag:42];
textField.text = #"Foo";
}

UITableView: Section identifier problem

I have an UITableview with a lot of sections with a dynamic amount of rows with a dynamic height.
Now i got the following Problem:
[indexPath section] returns the value of the (latest/ lowest/ highest-value) section in the view.
Now i have a section witch is very small and i can unfortunately "see" 3 sections in one time. How can i identify the section on top? Any ideas.
I need it because in every section are buttons which cause a change of the amount of Rows in the section ( depending on the section). Sometimes i increase the amount of Rows for wrong sections because i cannot identify the 'upper' section.
I hope i described it good enough.
You can get all the visible cells using the visibleCells method of the table view. You will need to sort the array to be sure.
NSArray * visibleCells = [self.tableView visibleCells];
NSArray * sortedVisibleCells = [visibleCells sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
NSIndexPath * indexPath1 = [self.tableView indexPathForCell:obj1];
NSIndexPath * indexPath2 = [self.tableView indexPathForCell:obj2];
return [indexPath1 compare:indexPath2];
}];
NSLog(#"%#", [self.tableView indexPathForCell:[sortedVisibleCells objectAtIndex:0]]);

Referencing UISwitches within UITableCells

I have a table view which I'm using for some settings in my app. The tables cells are all default (no customisation at all), and simply contain some text for their label and a UISwitch for the accessory view.
My problem is that I need a reference to the switch so that I know when it has been switched on and off.
Currently I am setting the 'tag' property of the switch to be that of the cell's index within the table (grabbed from [indexPath row] in tableView:cellForRowAtIndexpath:).
This is fine when you only have one Section in your table, but I am now adding a new section. The problem is that they are both 0 based indexed so the switches in each section will end up reusing the tags - which isn't good.
Any suggestions on a better way to achieve this?
Thanks.
If you know roughly how many sections and rows you will have, like oh, say, not more than 1 million rows per section, just hash the section and row like this:
const int oneMillion = 1000000;
int tag = (section * oneMillion) + row;
slider.tag = tag;
Then, to figure out the section and row, reverse the logic:
int tag = slider.tag;
int row = tag % oneMillion;
int section = tag / oneMillion;
NSIndexPath *indexPath = [NSIndexPath indexPathForRow: row inSection: section];
Now get the slider that is in the cell in that section,row of the table
UITableViewCell *sliderCell = [tableView cellForRowAtIndexPath: indexPath];
UISlider *slider = [[sliderCell.contentView subviews] objectAtIndex: 0];
This assumes the slider is always the only view in the contents of the cell.
This method is a bit longer than some of the other suggestions above, but it keeps you from having to cache references off to the side.
For each cell, set a delegate link back to the table view controller, and also some kind of row reference ID - then wire the switch to a cell IBAction method, that calls back to the delegate with the reference ID for that cell.
What you can do is either have an Array of arrays or a dictionary, key it by the section number (or in case of the array they will be in order of the section numbers), now to retreive a switch all you do assuming you know the section and the row number
UISwitch *switch=[[switchArray objectAtIndex:section] objectAtIndex:row];
or if you have a dictionary
UISwitch *switch=[[switchDictionary objectForKey:section] objectAtIndex:row];

iPhone SDK: Inserting and updating a UITableView with a new row

I have a tableView that needs to be updated after information has been inserted from another view. If I perform a
[self.tableView reloadData];
The very next time I insert more information in another view and try to reload the table, all the currently visible rows are duplicated.
In other words, when I start up the app I have:
tableView:
Row 1
Row 2
Then I submit some information that will also show up in the table and suddenly I have:
tableView
Row 1
Row 2
Row 3 <- info I just added
Row 1
Row 2
My numberOfRowsInSection implementation looks like this:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [ItemsController sharedItemsController].count;
}
My cellForRowAtIndexPath implementation looks like this:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
ItemsController* controller = [ItemsController sharedItemsController];
NSMutableArray* recentItems = controller.listOfRecentItems;
CustomCell *cell = nil;
NSUInteger row = [indexPath row];
if( row < recentItems.count )
{
Items* item = [recentItems objectAtIndex:row];
if( recentCellData == nil )
recentCellData = [[NSMutableDictionary alloc] initWithCapacity:[indexPath length]];
if( [recentCellData count] > 0 )
cell = [recentCellData objectForKey:[NSString stringWithFormat:#"%d", row]];
if (cell == nil) {
UIViewController * view1 = [[UIViewController alloc] initWithNibName:#"CustomCell" bundle:nil];
cell = (CustomCell*)[view1 view];
[recentCellData setObject:cell forKey:[NSString stringWithFormat:#"%d",row]];
}
// do some other stuff here
}
// Set up the cell
return cell;
}
What's the best way to update the table and avoid duplicating the currently visible rows.
Thank in advance for all the help!
The error isn't in how you're reloading the table, it's in how you're providing data to it. Set a breakpoint in the data source methods and the method that adds new rows to see where you're going wrong.
You'll only end up with five items if tableView:numberOfRowsinSection: returns 5. Thats the simple answer to your question, but I see other problems here. I'm wondering why you have this test: row < recentItems.count. Is that array the same thing as [ItemsController sharedItemsController].count? You really need to be using the same array for both methods.
(Also, it's not a syntax error, but you shouldn't use the property syntax for things that aren't declared as properties. You should write [recentItems count] instead.)
I'm also confused by the code you use to set up the cell. Cells are meant to be reusable. That is, you create one cell, then reconfigure it every time in your implementation of tableView:cellForRowAtIndexPath:. Your code creates a cell for each item in your list. This is very memory-inefficient, and will likely crash your program due to insufficient memory on the iPhone if you keep lots of cells in memory like this.
The recommended approach is to call dequeueReusableCellWithIdentifier:. If that returns nil, then you set up a cell using the initWithFrame:reuseIdentifier: initializer. The table view is very smart, and will only ask you to redraw the cell when it needs you to.
Your recentCellData dictionary looks really shaky to me, too. What if you insert an item after the item with key #"2"? All the items with key #"3" onward will need to be shifted one element to the right to work the way you expect. That's a ton of bookkeeping that seems rather unnecessary to me. If you really needed something like this -- and to be clear, I don't think you do -- why wouldn't you use an NSMutableArray, which is much easier to use?
I added a bit more info above.