This may sound a newbie question, however I'm new to iOS dev,
I want to understand when I should use UNIQUE identifier for the cells and when not for
- (id)dequeueReusableCellWithIdentifier:(NSString *)identifier
Actually in lots of places I've met code snippets where identifier was not unique.
But in my practice I've used unique identifier in order to keep the order of the UITableViewCells, otherwise the order was mixed when I've scrolled UITableView up and down.
So please help me to understand the concept of reusable cells, shan't each cell have unique identifier?
Thanks in advance,
You should use different identifiers only for different types of cell. If your table view had different classes of cell this may be your problem, or you have added subviews to a cell that vary in their presence from cell to cell.
When using an identifier, think about it in terms of your cell could contain the data of any previously rendered cell data, so you need to ensure your code overwrites that data, in the most simple case cell.textLabel.text.
I believe I've got the answer to my question. Thanks to Aaron's question.
I always try to initialize each cell only once in the same view (of course if it's not being edited in that view). I do this to enhance the performance and smooth the scrolling of the table view.
The difference is - now I know how it works. If I get it right, cell identifier makes the cells to stay unique and this way table does something like caching that information and then putting it to the right place (because of unique identifiers).
Thank you guys!
Always try to initialize each cell only once in the same view . I do this to enhance the performance and smooth the scrolling of the table view. The difference is - now I know how it works. If I get it right, cell identifier makes the cells to stay unique and this way table does something like caching that information and then putting it to the right place.
Related
Is there a way to make table view not recycle UITableViewCell so after all cells are loaded, it won't ask for cells(ie tableView:cellForRow...)?
I know I can put the table view in a scroll view and make the table view to have the same size as the scroll view, so all cells will be loaded, but some of my cells have variable sizes, then I need to update the scroll view's content size after the cells' sizes are changed.
Is there any other way to do this?
update:
Sorry for the misleading, actually I mean how to make it not REMOVE cells once created, so if there are ten cells, and there won't be any cell returned by dequeueReusableCell and after ten tableView:cellForRow: it won't call it again.
Simply not use reusable identifier will make it create new cell every time as needed, even the cell at position 1 has been created but then reused for position 2.
Set the reuseIdentifier to nil.
This is much better than using a different identifier for each cell, as the table can now dispose unneeded cells quickly. If they have some identifier set, there's no way to tell if you will ever reuse them.
So you don't have to miss the reuse part completely, just for the cells you don't want to. If the new cell contains the same subviews (maybe just layout and configured differently) - it might still be better to reuse.
Just don't use a cellIdentifier, or use a different identifier for each cell.
just dont use - (id)dequeueReusableCellWithIdentifier:(NSString *)identifier
in the cellForRowAtIndexPath method and create a new cell everytime.
Other way is to give a different cell Identifier for each cell you create.
Now, If you can elaborate on why you dont want the tableview to recycle its cells (which is one of the powerful feature of tableview), may be you can find out other ways to achieve the same thing with reusing the cells..!!
Hope it helps..:)
I am relatively new to Objective C/iOS development so I realize that this may seem like a basic question: For iOS 5+, I'm looking for a primer on how to create a tableview that has cells with a variety of data. For example, in my data array I might have data like:
Restaurant Name (basic string)
Restaurant Logo (string name of an image file)
Restaurant Rating (an integer)
In a single cell, I want to display the logo of the restaurant, then the name, and then show a number of stars based on the rating integer (ie a "4" would display a single star image 4 times).
I can't tell if I can do this with the standard table cell or if I need to create a custom table cell object.
Help!
Here is a good place to start.
http://cocoawithlove.com/2009/04/easy-custom-uitableview-drawing.html
One point they make is that if you subclass UITableViewCell then you have done something wrong. Instead, read it as most of the time customizing the standard UITableViewCell is sufficient.
For spectacular customization then deriving a class from UITableViewCell is fine.
I'll try to give you some suggestions on how to reach your goal based on my experience.
I think you can use both a default cell or a custom one.
In the first case, you have can use a simple cell (UITableViewCell) with a default style.
The properties you can use are: imageView for the logo, textLabel for the name and accessoryView for the rating.
Take a look to A Closer Look at Table-View Cells for info about table cell structure.
If you have to maintain a specific order for your cell content you need to create a custom cell that extends UITableViewCell and override layoutSubviews methods. I've already answered a question in this stackoverflow topic custom-uitableviewcell-with-an-optional-image.
In the second case you can use a custom xib or a completely fresh cell and do the stuff there. Out of there you can find lot of guides to do that. Here fews:
The one that #bbarnhart has written
custom-uitableviewcell
creating-a-custom-uitableviewcell-in-ios-4 (suggested)
P.S. For creating a rate view I suggest to take a look at how-to-make-a-custom-uiview-a-5-star-rating-view.
Hope it helps.
You can do this using a standard table view cell with an image and subtitle. The main text label is the restauraunt name, the image view holds your logo, and the subtitle can be made of the appropriate number of unicode star characters (for example, #"\u2605").
Im not sure if this is possible but I was just hoping to have a question answered about dequeueReusableCellWithIdentifier and if it could be applied to something other than a UITableViewCell. Maybe not dequeueReusableCellWithIdentifier exactly, but maybe something along the same idea.
I have a bunch of UIImageViews, that appear in a grid, they all have the same image, and the user can remove and add more to the grid so it is quite dynamic. But I was hoping that maybe there would be a way to reuse some of the images that the user has removed, because I'm seeing some pretty large performance issues after the user interacts with them for a little while.
Can anyone give me a little advice how I might do this?
There's no built-in mechanism, but it's not hard to create one.
Just add an NSMutableArray to your view controller. Every time you remove a view from the grid because it's moved off screen add it to the array. Every time you need to add a new view to the grid, check the array and see if there are any views in it. If there are, remove one from the array and add it to the screen. If there aren't, create alloc a new view.
That's really all there is to view dequeing and re-use.
You don't need to replicate the reuseIdentifier stuff because (I'm guessing) all the views in your grid will be the same class.
If you do need to have multiple different views, just have multiple queue arrays and use different arrays for different view types.
Why dont you create one UITableViewCell & add 2 ImageViews on them. Dont forget to add a unique cell identifier to them o that dequeueReusableCellWithIdentifier works as usual.
Something like this -
We have a scenario where we reuse the same UITableView to display different sets of records from the database as a user selects an item in a different UITableView (similar in concept to a splitviewcontroller, but all in the same view).
When the user selects a different area to view, we fetch the appropriate records from the database, update the Source with the new set of records, and call ReloadData.
The problem is that some of the cells in the UITableView still exist and are reused when switching between lists, resulting in invalid or overlapped data for various rows.
The question I have is: is there a method whereby we can tell the UITableView to discard all existing cells including those queued for reuse? I would have expected ReloadData to perform this task, but it does not.
Update with additional clarification:
Each cell in our table is composed of a variable number of subviews (we are trying to mimic a grid control). When the user selects a different list in the left-hand navigation, there is no guarantee that the subview positions (columns) in the newly selected list will overlap with those in the previous list. This is why we are looking for a method to remove the queued cells.
Since this is a situation that others may find themselves in, I will post the solution that we used, but am still interested in more "native" ways of doing this.
Here is how we solved the issue:
When the set of records being displayed is changed, we update the UITableView with a unique identifier for the current cell configuration (i.e. which list of data is the user currently viewing).
We then created a custom version of UITableViewCell and record the unique list identifier in the cell when it is created.
When we dequeue a reusable cell, we compare the view's current unique identifier with the unique identifier stored in the cell and, if they don't match, we discard the cell and create a new one.
Hopefully this will help someone down the road.
ReloadData does not clear the re-use queue. It simply triggers the callbacks to re-read the data which reloads the rows. As each cell get's loaded, if you're getting it out the re-use queue it will still be used. That's good even if the table view is re-used because the cell types are the same type especially since you use the CellIdentifier to ensure that.
But, it's kind of odd that you're overlapping data. When you get a cell out of the re-use queue, how are you putting the data in it? Are you painting the data directly on the cell? Are you adding subViews with the data (causing multiple sets of overlapped data)? Typically, a cell contains subviews like text labels and the data is set on them so there's no scenario where data gets overlapped - the subviews of cell just has their data updated ...
Your GetCell method needs to ensure that a dequeued cell is fully configured with the new data that it is going to display.
A common mistake is assuming that just dequeuing the cell for display will give you a fresh cell that you can use.
If you have done any customization with your cell, like adding views, modifies its properties (images, disclosure indicators, background colors) you must make sure in the GetCell method that is reusing a cell that every single one of those properties is properly set before returning the cell.
I have an NSTableView with some cells that where the value of enabled is set through bindings. I want to be able to change the colour of the cells depending on whether the cell is enabled or not. Previously I have done this through the NSTAbleView delegate method tableView: willDisplayCell: forTableColumn: row: which up until now worked fine. I've had to switch off the table delegate though and so I need to find another way to do it. I suspect it's a problem with an obvious answer, but how do I access each cell in the table? I can get the number of rows and columns in the table, and I can cycle trough them, I'm just not sure what method to call to get the cell in column i, row j.
Generally speaking, you shouldn't be cycling through the rows and columns. Your code should be able to do the right thing, given any row or column.
One way to do it is to write your own cell class and implement the appropriate drawing and highlighting methods that you'll find in the NSCell documentation. You'd implement
– drawWithFrame:inView: and probably -highlight:withFrame:inView:
Yet another way is to subclass NSTableView, and override -preparedCellAtColumn:row: to do whatever manipulation of the cell you want just before it's drawn.
The easiest way to do what you want though, is to just use the delegate method as you were before. Why don't you want to do it that way?
Assuming you don't want to color an entire column, the easiest way is tableView:willDisplayCell:forTableColumn:row:, since there is only one cell per column (the view uses the same cell for that column in every row).
Why did you get rid of your delegate?