This is more of a theory question than a programming question. As you know when you instantiate a table view in iOS, you have to account for dequeuing and reusing table cells, when they are scrolled in and out of view.
The confusing thing to me is, all the data that populates the cells is cached anyway. When you look at a web page in safari, you are scrolling past a lot more images and text that remains after you scroll past it. I have iOS games installed that use many times more data (e.g., Asphalt 6) than a simple table. So I'm just curious why Apple goes to the trouble of dequeuing and reusing table cells. Thanks.
It's not about the amount of data in the model. It is more so about the amount of memory that is used in creating the Cell views. If I have a table that is going to create over 1000 UITableViewCell objects, why would it create them all when only about a dozen or so can appear on the screen? Don't just think about the data that is held and being displayed, think about the memory that is taken up in the objects that are displaying the data, the UITableViewCells.
It's just good memory management. There's no telling how big a table could be, so better safe than sorry. You only ever need the memory for however many cells fit in a view.
Related
I am wondering what exactly happens, when you dont use dequeueReusableCellWithIdentifier in the cellForRowAtIndexPath-method.
In one Project I am collaborating we have different types of custom UITableViewCells which all appear in one single tableview. So here we fill arrays with all TableCells that should be displayed. These arrays are not very big (10-15 Cells) so for us that way works even not using any identifiers for dequeueReusableCellWithIdentifier. The next question is how at all you could use identifiers resp. dequeueReusableCellWithIdentifier when using different Cells in one single section of an UITableView. Is someone here hwo can explain, what exactly happens in background? Regards Nils
The dequeueReusableCellWithIdentifier is something that reminds me of Flyweight pattern.
Since allocation and instantiation of a cell can be an expensive task, using this mechanism you have the opportunity to create only the first visible cells and later reuse them just changing their contents. Scrolling animation must be as fast as possible to give a good experience to the user.
Is it worth it? Yes and it basically comes for free, we just need to pay attention that some old data can be still present in a new visualization, the trick is to always implement the method -prepareForReuse() correctly, here, you can eventually wipe all displayed data before setting the new one.
If you want to use different cells in the same section is absolutely possible, also if they have different height. You just need to crate different cell identifiers, one for each cells and tie them somehow along with your data.
I usually map data to be displayed in struct (swift) or dictionaries along with a key for the cell identifier to be used.
If your type of cells are representing themselves while scrolling you should dequeue them.
In my app I should create a view with a loto of informations;
these informations are divided in 4 section, every section can contain text, images lists ecc...
this is a brutal example...
Now I'm dubious to what type of solution to adopt.
In a my fast opinion a big scrollview is difficult to organize. And a big tableview with section is complicated to organize with code... What are your ideas?
UITableView is optimized for "reusable" cells, which is appropriate for scrolling in long lists.
Another benefit of using an UITableView, as others suggested, is that it only instantiate visible cells, so memory consumption is reduced.
In your case, since your content looks specific and non repetitive, I would suggest using a simple UIScrollView which is easier to use. (UITableView inherits from UIScrollView btw)
If memory/performance is an issue, then prefer UITableView or simply write your own logic to only instantiate views that are visible (by using scrollOffset for example)
EDIT:
On second thoughts, in your case, UICollectionView is surely a better candidate than UITableView.
Especially if you plan some day to do something like a 2 columns layout on iPad...
You should go with UITABLEVIEW, easy to manage easy to understand, more reusability and good memory management
If you have lots of content to scroll through, a UITableView might help you with keeping memory usage down.
When a cell scrolls out of sight, it gets removed from the view and kept around by the UITableView for later use (via -dequeueReusableCellWithIdentifier:). If you run low on memory then I believe that those invisible views (UITableViewCells) will get released. This basically means that your app will only keep views in memory that are actually visible. More will be cached, but can be purged any time if needed.
If you display a lot of data, and just add it all to a UIScrollView it will potentially use much more memory than if you used a UITableView. You might have to implement a similar mechanism to what UITableView does to remove (and potentially release) invisible views.
So, you can basically achieve the same effect, but a UITableView does a lot of that work for you already.
If you display lots of data (probably more than about two screens full) I'd lean towards using a UITableView.
This sort of thing is very easy to create in Interface Builder now with static cells; you can layout the entire interface visually and set up outlets for the cells (and/or their subviews) in order to configure the content in your view controller.
All,
I hope most of you know that with ios7 there is not need to do a null check for tableview reuse
if (cell == nil) {
But unfortunately, because of that the cells are always reinitialized, as we put the code in the same method for initializing values. The problem is only with text fields inside the tableview though.
Let me explain the scenario. I have a table view with multiple rows, and some rows contain multiple text boxes. I populate the textboxes with data from server when the page is loaded. Since the cells are always re-initialized as i explained above, whatever I enter in the field goes away and the server data is re populated once i scroll down and come back to the initial stage. This is because the populating the data code is also in the same place. After fetching a reusable cell it populates the data.
Previously till ios6, we used if(cell==nil) and hence we loaded server data inside the cell and when reusing the cell, this piece of code will never be called.
I have other dirty solutions, but would like to know if someone else has a graceful way of dealing this. Please help.
You just don't store any data in the table view cell but in the model that fills the table cell. This is always the way it should be done.
Looking from the MVC standpoint than the UITableViewCell is a view. Since it is reused by iOS you should use a model to the view.
Yes, this is the expected behavior of UITableView. For performance reasons, cells are reused. Thus, it is your responsibility to populate the views in a Table View Cell every time tableView:cellForRowAtIndexPath: is called.
The thing I don't understand from your question - are you making a network call every single time a cell comes into view? If so, cache the results somewhere. Or, if it's a small amount of data, consider just doing it all in one shot at the beginning (still need to be asynchronous though).
One thing I see a lot of developers do is move a lot of code into UITableViewCell subclasses, which sounds like a good idea because it's modular, but makes solutions for problems like this more difficult. Have the Table View Data Source manage the network calls.
If you need some inspiration, look at Apple's LazyTableImages sample.
I'm trying to create a custom view that can display a large amount of data, similar to the way UITableView is able to display many rows of data. Right now I'm displaying the data in a UIScrollView, but after I reload the data several times my app starts to receive memory warnings.
What's the right way to design a custom view to display a large amount of data, and how can I avoid these memory warnings?
It doesn't. UITableView loads only as many rows as it can fit on the screen. When it needs more rows it asks the data source for them. This gives the appearance that the table contains all the data without all the overhead of copying everything at once.
When your tableView cell is too heavy means, it has imageView and more than one text label better create a custom cell by subclassing the UITableView.
Make sure that in custom cell the subview should be added only once and reused for cells. Just you need to sent the image of imageview or text of label. Even if you have so many cells in tableview the performance will be good.
And also make sure that if you are loading images from server don't fetch every time when you are setting image for cell. use image cache.
The following link might me useful for loading data to table view from server.
http://www.raywenderlich.com/4295/multithreading-and-grand-central-dispatch-on-ios-for-beginners-tutorial
I have a UITableView that collects data from a database. What I would like to know is if there is some way I can iterate in the UITableView collection and check the values of the cell? The reason I ask is because I would like to update each cell based on the current value that it has (change font, size, color, etc.). I've seen in another SO post regarding this topic, but since the cells are already created and their values are changed it is a bit harder for me. I was thinking of iterating through the UITableView before I call reloadData, but any other suggestions are welcome.
You should not iterate over the cells of UITableView, because some of them (in fact, most of them) may not be present until you request them. UITableView aggressively recycles its cells, so if a cell is not visible, it is very likely that you would be creating it from scratch only to put it back into recycle queue moments later.
Changing your model and calling reloadData the way your post suggests would be the right solution. iOS will ensure that it runs the update in a smallest number of CPU cycles possible, so you do not need to worry about the cells that are already created. This is also the easiest approach in terms of your coding effort.
A table view is for displaying data. The properties of your table cells should only be written to, not read from. The appropriate way of handling this situation would be to update your underlying model objects -- the objects that you use to populate the table view -- as the data changes, and then reload the affected rows.
The issue you'll encounter is that UITableView reuses table cells. Once a table cell scrolls off the screen, it's quite likely that the table view will reuse the same cell to display a different row.
This means it's fundamentally not possible to iterate over the table cells. When you need to refresh a row because its data has changed, you should call reloadRowsAtIndexPaths:withRowAnimation: (or reloadData if all rows have changed) and if the row is visible on screen, UITableView will call your data source methods and give you an opportunity to configure the cell for display.