I have a custom UITableViewCell that seems to appear multiple times on my table before I even start scrolling. It seems dequeueReusableCellWithIdentifier isn't working properly. Here's my cell:
MyCustomCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[MyCustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
... setup ...
}
When I call reloadRowsAtIndexPaths: on my tableView, for some reason it doesn't dequeue that cell and it recreates the new one. Then when I scroll back up and then down again, sometimes my first cell dequeues, sometimes the second cell dequeues. MyCustomCell is basically a textfield so depending on which one dequeues, the text has different data each time.
Is there something more I should be doing in my custom cell? Thanks in advance.
You mention reloadRowsAtIndexPaths: in your question, but the method is actually reloadRowsAtIndexPaths:withRowAnimation:. The fact that the reload can be animated matters. For example, to animate UITableViewRowAnimationLeft, the table view needs to slide out an old cell while sliding in a new cell. Both the old and new cells are on screen simultaneously, so the table view can't just use the same UITableViewCell object for both. That's why “it doesn't dequeue that cell and it recreates the new one”. It needs a new one because the old one is still visible.
You need to make sure that when you receive a tableView:cellForRowAtIndexPath: message, you fully initialize the cell (whether dequeued or newly created) to show the data for the requested row, and only the data for the requested row.
Also, you can't keep your own mapping from the row's indexPath to the cell, because (during animations) there may be two cells for the same row. Instead, if at any time you need to get the cell that is currently showing the data for a row, you need to ask the table view for the cell by sending it a cellForRowAtIndexPath: message.
From the code you show, it looks as if you only set up your cell's content when a new one is created. Since there's no way of knowing which cell you'll be given from the cache, you need to configure the cell whether it's new or one that's being re-used.
Related
I am using a UITableView to display some items and i have implemented a UISearchBar to this UITableView.
If the user presses the cell, a checkmark appears (accessory type of the cell is changed) and when pressed again the checkmark accessory disappears.
My problem is when the user searches using the search bar, all the checked cells are not checked anymore, no more checked cells at all.
I've been trying to fix this and searching for it for a while but no results ...
Any help ??
Thanks you.
That is because your table view where you put the checkmarks and the table view that you see after you enter something in the search bar is not same. To have the same check marks on the search table view cells, you need to explicitly add the checkmarks.
I can't see the way you are adding and removing check marks. So, in theory, what you need is a way to know which cells have check marks. So, let's assume you have an array of items and a parallel array which holds the 1 or 0 to signal if the items have the check marks when 1 means check marked and 0 means no check mark.
Let's call this parallel array, checkMarkSignalArray. Now, in your cellForRowAtIndexPath method, you can do something like-
if(self.resultSearchController.active){
cell.textLabel.text = [self.filteredItemsArray objectAtIndex:indexPath.row];
if([self.checkMarkSignalArray objectAtIndex:indexPath.row]){
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
}
i have the indexPath number... i need to remove the cell accessory from that cell based on the number in the variable i have?
NSInteger *removeAccessoryFrom = 3;
[studentTableView cellForRowAtIndexPath:removeAccessoryFrom].accessoryType = UITableViewCellAccessoryNone;
It doesn't work like that. You need to reload the table data (either for the whole table or for just this row) and, inside cellForRowAtIndexPath, set the accessoryType to UITableViewCellAccessoryNone conditionally. In other words, you keep a list, or have some other way of knowing, at every moment, and for the entire table, exactly what cells get exactly what accessory. That way, any time cellForRowAtIndexPath is called, you can configure this cell for this index path correctly.
I created tableview that read from url (any cell has name of book) and when clicked any cell gone detailView.
in detail view exist UIScroll that read any image from url and I create it.
but my problem this place. I don't know what read images in UIScroll related any cell.
this is URL : ".../mamal/book.php?p=%d&b=%d"
(p and b display number page and number book)
I want when clicked first cell (book1) compiler gone next page and display images related book1
and etc.
You have to use UITableView protocols <UITableViewDataSource,UITableViewDelegate> in your .h file then use below delegate method which you give which cell is clicked
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"Clicked cell-> %d", indexPath.row);
}
You can also identify the currently selected row using the property indexPathForSelectedRow.
i.e if you want to know the index path of currently selected row at any point of time without using the delegate methods (not saving it during selection) you can use
tableView.indexPathForSelectedRow
If you want to pass around the value between multiple view controller you can declare an instance variable in the view controller you want the value to be passed and store tableView.indexPathForSelectedRow in this variable during initialization. A quick search on so should help you with that.
My table view covers part of the view. If I have 20 objects, I am displaying all of them in a tableview. But I want to know that how many cell are loaded that are visible to the user.
(i.e. first 5 cells data is visible for me: when I scroll down, the remaining cells will load. Here I want to know without scrolling how many cell are loaded.)
Is this possible?
You can use [tableView visibleCells] count], which returns numbers of the table cells that are visible, if I understand correctly what you want.
The below code will give you the array of indexpath of cells currently visible
NSArray *visiblePaths = [self.tableView indexPathsForVisibleRows];
after getting the index path you can easily access the cell at a particular indexpath
Its usually : (tableView's height / cell row height ) + 1
Can you take the size of the visible part of the table, and then the size of one cell, and divide them to know how many of them fit in the screen?
I have a NSTableView that contains a NSButtonCell in one of the columns. I can set up the action that is called when the button is clicked in Interface Builder fine, but I can't find anyway to determine which row in the table that the button exists in. Is there any way to do this?
Thanks. :)
The cell for a particular column is reused throughout the whole table so there isn't one cell per row by default. You can get the the row that was clicked on though in your action method by sending the clickedRow message to the cell's table view.
NSInteger clickedRowIndex = [tableView clickedRow];