in iphone uitable view data desplay problem - iphone

i have a uitableview in that i display data with the help of network queue . I use CellIdentifier like this,
NSString *CellIdentifier = [NSString stringWithFormat:#"%i_%i" , indexPath.section , indexPath.row];
and check condition
if(cell ==nil)
{
}
so data is loaded only one time .
by doing this, it loads data but the problem is in imageview. the image size is big so it takes some time. if image is not loaded and user scrolls the table then that image is never seen. To see the image we have to wait till it is loaded and then we scroll the table.
Is there any way to load the image again which are not loaded.
I dont want to load all data again .

You understood if(cell == nil) {} wrong.
This condition should not be used so your data is only loaded one time, this should be used to construct a new cell only when necessary.
You have to setup each cell outside of this condition.
And you should definitely not use a different CellIdentifier for each cell. This is a bad hack introduced by people who are to "lazy" to implement lazy loading of cell images correctly.
You should see the LazyTableImages example from apple to see how it should be done.

For loading images in table view, you can use good LazyTableImages Example by Apple. You don't have to write this type of code (different cell identifier for each). You have to reuse table view cell as per apple document otherwise it will take too much memory while scrolling.

Related

Disable uitableview disable reuse when scrolling in iOS

I want to disable reloading table view when scrolling. Now, my app when user scroll the uitableview, cellForRowAtIndexPath has been recalled.
Things in viewDidLoad
[listingTableView registerNib:[UINib nibWithNibName:#"TripCardCell" bundle:nil] forCellReuseIdentifier:[TripCardCell cellID]];
Things in cellForRowAtIndexPath
if (cell == nil) {
        cell = [[TripCardCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:[TripCardCell cellID]];
        cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
    }
UITableViewCell Class Reference
The reuse identifier is associated with a UITableViewCell object that
the table-view’s delegate creates with the intent to reuse it as the
basis (for performance reasons) for multiple rows of a table view. It
is assigned to the cell object in initWithFrame:reuseIdentifier: and
cannot be changed thereafter. A UITableView object maintains a queue
(or list) of the currently reusable cells, each with its own reuse
identifier, and makes them available to the delegate in the
dequeueReusableCellWithIdentifier: method.
Advantage of reuseIdentifiers
Using dequeueReusableCellWithIdentifier for the tableView, you can
greatly speed things up. Instead of instantiating a lot of cells, you
just instantiate as many as needed, i.e. as many that are visible
(this is handled automatically). If scrolling to an area in the list
where there are "cells" that haven't got their visual representation
yet, instead of instantiating new ones, you reuse already existing
ones.
disable reloading tableview when scrolling
You cannot block the cellForRowAtIndexPath: from calling when
scrolling the tableview. If something need not happen every time, You
may keep it in if condition.
if (cell == nil)
{
//Functionality goes here when it not needed to happen every time.
}

How to populate an image in UITableViewCell even if user scroll the table

I'll try to explain my self, I have ContactsViewController that shows a table view with a list of contacts (the model is an array of Contact objects), each cell display an image of a contact.
Currently what I do to populate the cell's UIImageView is this:
1. I override the Contact image property getter -
- (UIImage *)contactImage
{
if (!_contactImage) {
_contactImage = [[UIImage imageNamed:#"placeHolder.png"] retain];
[self asyncDownloadContactImageFromServer];
}
return _contactImage;
}
Then when I finish downloading the image I set it to the contactImage property and I post a ContactUpdatedImageNotification.
My ContactsViewController then get this notification and reload the cell of this contact, this will set the downloaded image to the cell's imageView.
The result of this is good async fetching of the images without blocking the UI while the user scroll the table view.
BUT there is something small that bothers me, when the a user scroll the table view and reveal new cells the new cell's image get download as expected but the cell's imageView is not updated with the new downloaded image till the user pick up his finger.
I supposed that I need to do something in another thread to make this effect, but I don't know how?
The image is not updated until the user stops scrolling due the code being executed in the default runloop, which gets delayed until scrolling finishes. This other question deals with the difference between the runloops, NSDefaultRunLoopMode vs NSRunLoopCommonModes and it precisely recommends not updating the images while scrolling since that can introduce jerkiness in the scrolling itself if you are not careful.
Also, now that you know about the existence of these runloop modes you will be able to find much more information about them in the xcode documentation or internet.
Hey Eyal visit following url...you will get answer and as well sample code...
tableview with different cell with different images
Hope this will help you...

Custom UITableViewCell woes

I have an iPhone app with a form input screen. I did this by making a custom UITableViewCell that has a UILabel and a UITextfield. I set it up so that the "cellForRowAtIndexPath" fetches the appropriate value from Core Data, and the UITextField's "textFieldDidEndEditing" method saves the appropriate value to Core Data. It works great... except:
If I edit a text field, then scroll it off screen, then click on another cell's text field:
The cell has been autoreleased because it scrolled off screen
The "textFieldDidEndEditing" gets a BAD ACCESS error
I understand the problem completely, I'm just not sure the best way to fix it. My first thought was to add the logic from "textFieldDidEndEditing" to "dealloc", but that seems hacky. Any suggestions?
I ended up using a delegate method for scroll view (which is built in to the UITableView). When the user starts dragging, I resign first responder.
This works perfectly because it looks nice, and "textFieldDidEndEditing" gets called when the user starts to scroll, which is always before the text field goes off screen.
disable scrolling while editing
retain your textField
that are the things you could do. In my opinion its best to disable scrolling while editing because the user has no need to, so make sure he also can not do so. Limit the things your user can do, makes it more "secure" for you and easier to use for the user.
If you are not sure about such things just look at what apple does, they are always right in their applications. Like in the settings app on iOS 5, when you change your phone's name. You simply get 1 row in the next tableview so you can't really mess anything up as the user..
In your custom cell's dealloc, set the textfield's delegate to nil
I had a similar issue... The problem lies in the reusable cells as part of the Table View. Every time the table is scrolled, the cellforRowatIndexPath gets called, and dequeues a cell and returns it. Sadly, this functionality doesnt work well with cells having retainable data such as labels. Hence you must opt for your own method of dequeueing the cell.
I have an NSMutableArray called cells which holds all my cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
CustomTableViewCell *cell = [self dequeuwReusableCellwith:indexPath];
if (cell == nil)
{
cell = [[CustomTableViewCell alloc] init];
[cells addObject:cell];
}
// Configure the cell.
NSString *temp = [NSString stringWithFormat:#"Cell %d",indexPath.row];
cell.textField.placeholder=temp;
return cell;
}
and this is my custom method to deque Reusable cells.
-(CustomTableViewCell*)dequeuwReusableCellwith:(NSIndexPath*)indexpath
{
if([cells count]>indexpath.row)
{
return [cells objectAtIndex:indexpath.row];
}
return nil;
}
Hope this helps...

iPhone - Slow scroll on TableView

i've problems with the scroll of my Table View. I have a custom cell that i load with this code :
if (cell == nil) {
[[NSBundle mainBundle] loadNibNamed:#"CustomCellQuartieri" owner:self options:NULL];
cell=customCell;
}
This is the code. customCell is an UITableViewCell object with a own xib. The controller of the xib is my view controller where the table is placed in. I load 2 label and one imageView from the internet. What is the problem? And how can i make my custom cell reusable?
Thanks
To make your custom cell reusable, set the identifier propertie in Interface Builder.
Who do you load the data from the internet (Async)?
Since you are using a custom UITableViewCell you have to set the identifier string property through Interface Builder, and then dequeue the cell in the usual way, using that same string as the key. This way your app will not create a new cell for each row of the table, but will reuse the already present cells, reducing build and presentation times.
If this won't fix the issue, you should look at the internet connection, to understand why data loading is so slow. If you own the server that serves the data, you would try to speed it up, otherwise you should look for a different or more efficient way for loading data remotely. Some code example would be great.
Edit
As stated in the comments, the slowness could be related to the loading time of remote images. You could try to build a local dictionary, of something similar, in which you'll save the images you already loaded associating them to their URL as the key, while you'll read remotely those you still don't own. This will work like a local cache to improve loading time for remote data.
The problem was that images have to be loaded asynchronously. Search SDWebImages on Google.

cellForRowAtIndexPath returns nil on device

I spent few hours trying to resolve one very strange issue, but I really don't know how to proceed.
I have a grouped UITableView referenced from XIB populated with custom (subclassed) UITableViewCell cells. All the cells (two section with one cell each) are visible and I am trying to get one of them by calling:
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:1];
LocationSearchFilterCell *cell = (LocationSearchFilterCell *)[filterTable cellForRowAtIndexPath:indexPath];
On Simulator 4.2 the cell is returned properly;
On Device 4.0.x the code returns NIL;
On Simulator 4.0.x the code returns NIL;
On Simulator 4.1 the cell is returned properly BUT NOT on Device 4.1.
The strangest thing is that I am using this approach on few other places within the application and the cell is always returned properly. I guess it is some strange combination of me doing something differently combined with some iOS bug.
Any idea ?
P.S. In situation where NIL is returned, by using GDB I get the pointer of the cell when it is created and call:
(gdb) po (void *)[filterTable indexPathForCell:(UITableViewCell *)0x7b08520]
and I get a valid index path (that matches the one I am providing) which means the cell is valid and present into the table view.
I have even tried passing the object returned by this last call (by pointer) and I still get NIL.
Interesting,
It turned out someone is hiding the table view before I try to get the cell (stupid me :)).
What I was doing was, triggering an animation to hide the table view (nested into some methods I am calling from the method where I try to get the cell). Because I was stopped on a breakpoint the animation was also stopped, so it seamed to me like the table view is visible.
What I don't understand still is why the table view is threaded as hidden although the animation is still not finished (and I only change the frame in the animation and set the table hidden after the animation is finished) ?
I guess the answer to this question is the key point why on different combinations of Device / Simulator / iOS I get different behavior. Anyway the solution is as simple as moving the two lines I've posted above at the top of the method.
Thanks to Rits for his question that triggered my reasoning ;)
regards