cellForRowAtIndexPath to load 3 cells above and below the visible cells - iphone

I know that cellForRowAtIndexPath only loads visible cells. Is there a way to force it so that it loads the 3 cells below and above it?

No, cellForRowAtIndexPath only loads the current cell.
Your question suggests that you're doing something that is computationally expensive or slow in your cellForRowAtIndexPath. For example, you might be doing lazy loading of images, but also want to "prefetch" some of images you need for candidate "next" cells in order to diminish the user's experience of the lazy loading. Generally, though, you wouldn't actually prefetch the UITableViewCell objects, themselves, but rather just the pieces of data that those cells need.
You might need to give us more information about what sort of stuff you feel the need to prefetch, and we can provide better counsel. It's a non-trivial issue, somewhat contingent upon having a well-designed model that your controller uses when presenting the view. You might want to share a little about your model and the nature of the stuff that you want to make sure is on-hand for the previous three and next three cells.

UITableViews usually take care themselves of the whole process of deciding when to load specific cells. They automatically remove invisible cells from it, sometimes storing those cells in an internal reusability queue.
UITableView provides a mechanism you can use to speed up the cell creation process by retrieving pre-alloc'd cells when available. If you use this method properly you should have no trouble with the scrolling speed in your table views. To do so, you need to configure the reusabilityIdentifier for a cell on creation, and call the method -[UITableView dequeueReusableCellWithIdentifier:] when you need a new cell in your cellForRowAtIndexPath: implementation.
It should be feasible for you to have your own queue of reusable and preconfigured cells if you still need more speed - although the advantages you can get from implementing something like this remain to be seen (you'd have more rows ready to use, but would also slow down cellForRowAtIndexPath: for the cell being requested). You would also need to be very careful not to clash with UITableView's standard queue.
Check out Apple's UITableView reference for more info on the reusability mechanism.

Related

UITableView Dynamic vs. Static Cell Allocation Performance / Memory Usage

Could anyone tell me the tradeoff in performance/memory usage between using static and dynamic cells in a UITableView?
Here's my situation: I have a TableView with 6 different sections. The first section is the only section in my tableView that holds a different number of cells each time the view loads, depending on the current state of the app. i.e. I have declared 12 static cells for that section in interface builder, however I only display a certain number of those cells depending on the user's interaction with the app thus far. The other 5 tableView sections all contain UISwitches and textFields that never change.
So say I statically allocated 50 cells for that first section, but still only displayed maybe just half of them depending on the state of the app. I would want to be able to display up to 50 cells though. How would this affect the speed or performance of my app? Would doing the entire tableView dynamically and redrawing the switches and textFields for the other sections each time lead to a better application performance?
UITableView itself is only tangentially related to performance in this situation. The real issue is how and when you allocate new cells.
If you have static cells whose contents never change, and you create them using the interface builder (née Interface Builder), you will see that allocation happening only once, usually in -viewDidLoad, and for the lifetime of that table (or at least until -viewDidUnload) these cells will exist and not need to be reallocated.
But this is a trade-off. Now your cells will load faster, but your app will have more memory. You'll just have to decide on a case-by-case basis whether this is slowing down your app dramatically, in which case you may want to lazily load your static cells the typical "dynamic" style in your data source cell-fetching method.

How can I make my custom UITableViewCells as fast as possible?

I'm creating custom UITableViewCells, and I'd like to make them in a way that allows the table view's scrolling to be as smooth as possible. In their current state, with a custom background image on each cell using the cell's backgroundView property, scrolling is is still fairly smooth.
But my question is, how can I add content to the cell and maintain this? The cells are fairly different from each other -- one may have a single label, another may have two labels and an icon, and another may have a bunch of other controls.
I've found that using unique cell identifiers for non-similar rows makes the overall experience laggy, so I need a method that allows me to use the same cell identifier and have very different cells.
Should I be using an XIB for this? If not, how should my subclass function? I was thinking of adding all of the controls to the cell, and only hiding/using the ones necessary at the time. Is there a cleaner way?

Threaded thumbnail-loading for imageview in a table cell

I'm looking for suggestions on how to make an efficient thumbnail-loader for navigation-lists in the form of tables. I can start a thread and download and cache the thumbnails, but I'm unsure on how to update a table cell with the image (a cell either visible or outside the view).
I think the app Blocket does what I'm after, if I remember correctly.
I'd like to set a placeholder image, and as the thread loads each image, it updates the cells. The placeholder could be an animated activity indicator (spinner), if possible.
Are there any terse example-code out there, or can you give suggestions on how to communicate the update to the cell and force it to display the image immediately?
Interesting problem.
I guess at some level you'll need to replace the existing cells in the table view via the reloadRowsAtIndexPaths:withRowAnimation: UITableView method, so I suspect you'll need to keep a lookup of cell contents -> indexPaths so you know which cells to update when the relevant asset becomes available.
However, you'll need to avoid breaking the existing cell re-use system. (i.e.: there's no value in pre-creating all of the cells in advance.) As such, much of this work should be done within the - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath UITableViewDelegate method, I suspect.
That said, hopefully you'll get a better response than these somewhat vague ramblings. :-)
Made the nicest threaded thumbnail loading I've seen yet on iPhone :D The hardest part was cancelling a thread when navigating away from its table. An NSThread loading images and performSelectorOnMainThread waitUntilDone:YES for when updating the cell.imageView, passing objects (cell, tableView, indexPath etc) in an array to bypass the limitation of passing only one object in withObject. Looks royale with a quick fade-in of each image as they load :)

How do I create a TableView like in network Settings App on the iphone?

How do i make such a Table view? So if I turn on the switch, 2 cells should be added.
I've already tried
[tableView numberForRowsInSection:6];
[tableView reloadData];
but this doesn't work as expected :(
any ideas?
The best thing would be 2 sections the first section contains 5 cells, the second section contains one cell with a switch turned off and if the Switch has changed 2 cells will be added to section 2.(Added with an animation :))
mhh..
Thanks in advance, I'm very excited on every answer :)
Where did you pull this -numberForRowsInSection: method from? As far as I (and the documentation) know, it doesn't exist and has never existed as a method of UITableView. Guessing is going to get you nowhere, much less inventing methods from thin air.
Perhaps you should review some tutorials that cover the basics of using UITableView before you attempt this. I doubt someone is going to take the time to write you a full class to do this and put it in an answer, and you'll be much better off in the long run if you don't simply try to copy/paste code that you don't understand. There exists much documentation and examples that cover UITableView, and that's just considering what's available from Apple - UITableView is such a frequently used class that searching Google for something like "UITableView tutorial" is going to give you pages and pages of results.
I will give you a quick overview of what you would need to do, though:
1. Of course, you can start with the UITableViewController template in Xcode and start customizing it to fit your requirements...two sections, however many rows per section, etc, determining that based on some model-level objects if necessary.
You'll need to either create a custom UITableViewCell subclass or customize the default UITableViewCell layout a good bit (at least by adding a UISwitch subview) when you create new cell objects in tableView:cellForRowAtIndexPath:.
The UISwitch should be configured to send a message to your view controller when the switch's value changes using -[UIControl addTarget:action:forControlEvents:] for the UIControlEventValueChanged event.
In your implementation of the action method for this switch value change, you'll need to implement logic to determine whether rows should be added or subtracted, and then actually add or subtract the rows. You can use beginUpdates/endUpdates, insertRowsAtIndexPaths:withRowAnimation: and deleteRowsAtIndexPaths:withRowAnimation: to have the nice smooth row animation behavior instead of simply calling reloadData.

How expensive is UITableView's reloadData?

I'm curious just how expensive in as far as resources go is UITableView's reloadData? I have an app which will make roughly 10 subsequent HTTP requests, and as it gets data / preps, it reloads the tableView. As the data set grows larger and larger, it's becoming very sluggish. I'm trying to figure out if it's because of the amount of times I'm reloading the tableView or because of how I'm grabbing/parsing the data.
What's the best practice in this case?
From UITableView.h:
- (void)reloadData; // reloads everything from scratch. redisplays visible rows. because we only keep info about visible rows, this is cheap. will adjust offset if table shrinks
"This is cheap."
implement your table view methods well and it'll be no big deal to call this function all the time.
On a side note, you should try to use the appropriate methods to animate adding and removing rows if you are thinking of using reloadData for that.
The best practice is to have your implementation of cellForRowAtIndexPath: do as little work as possible. In fact, it really shouldn't be doing any work except populating the UITableViewCell instance with the data it needs to display.
You should be using cached UITableViewCells so you don't have to allocate a new cell each time. If you can do your parsing and such in a separate thread and make the parsed data, ready to present, accessible to cellForRowAtIndexPath:, you shouldn't have any performance problems.
You didn't say if you were using a custom UITableViewCell subclass, but if you are, deep view hierarchies can also present a performance problem, since each view in the hierarchy gets drawn. The flatter you can make UITableViewCells, the better.
Hope that gets you moving in the right direction.
Best thing to do is profile your app to see where it is slow.
That said, if your table cells are all the same height, then I think
reloadData
only has to call
cellForRowAtIndexPath
for cells that are visible on screen.
Table view reload expense is:
Figuring out how many sections and
rows per sections you have
getting row heights.
Row heights in particular are figured out for all elements of the table, anytime you call reload data.
The remaining expense is cellForRowAtIndexPath, which is usually not too bad because it only is called for as many rows as are on the screen. It can be bad when scrolling if you do not reuse cells like you are supposed to.
The key for you is probably, to ask yourself what triggers the HTML load and possibly move that into a background thread.
Boot To The Head is correct.
I'm doing a progressive one-by-one article list update in Instapaper, and I call -reloadData on each completed download. Sounds similar to what you're doing. It doesn't result in any noticeable performance slowdowns.