I use datamodel to store 2 objects : Video, Images.
Video contain just string attributes and Images have 2 "Binary data" attributes.
At the start the 2 binary data attributes was in the video object.
But all videos are loading during initialization of UITableView.
For 400 videos binary data represent 20 Mo, so imagine with 4000 videos...
Now with 2 objects the UITableView loading work well.
I load binary data when it's necessary in the method : tableView:cellForRowAtIndexPath
But now more I scroll into the list, more the memory grow up :(
look at my method :
- (UITableViewCell *)tableView:(UITableView *)myTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"videoCell";
Video *theVideo = (Video *)[[self fetchedResultsController] objectAtIndexPath:indexPath];
VideoCellViewController *cell = (VideoCellViewController *)[myTableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
[[NSBundle mainBundle] loadNibNamed:#"VideoCellView" owner:self options:nil];
cell = editingTableViewCell;
self.editingTableViewCell = nil;
}
cell.video = theVideo;
return cell;
}
And the method setvideo in VideoCellViewController
- (void)setVideo:(Video *)newVideo {
if (newVideo != video) {
[video release];
video = [newVideo retain];
}
NSData *imageData = [video.allImages valueForKey:#"thumbnailImage"];
UIImage *uiImage = [[UIImage alloc] initWithData:imageData];
smallImage.image = uiImage;
nameLabel.text = video.displayName;
[uiImage release];
}
Even without set the smallImage, I have memory trouble.
If I load the image object, it's never release.
I try a lot of solution to release memory without succes...( didTurnIntoFault, release, CFRelease...)
In performance tool, I can see my binary data as CFData.
I use a lot iPhoneCoreDataRecipes and PhotoLocations sample.
I need help to clean my memory ;)
Thanks
Samuel
Clearly there is something going on with your table cell creation logic. Let's take a look at a typical cellForRow delegate handler first..
static NSString *MyIdentifier = #"MyIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:MyIdentifier] autorelease];
}
// do stuff with cell
return cell;
Here we see we are
trying to get a reusable cell
if that fails (nil) create a new one and pass the reusable id to the ctor
then do stuff with the cell (new or existing) and return it
If you do not key the cell for reuse in the table view, you will always get a 'nil' cell returned from the dequeue, hence the need to create new cells every time. This will cause memory to continue to grow as you scroll around, but stay fairly flat when idle.
EDIT:
Assuming your cell is fine, then you need to narrow down if it's the video data or the image data that is leaking. What is smallImage? And are you sure you do not want to do everything only when the video is new?
- (void)setVideo:(Video *)newVideo {
if (newVideo != video) {
[video release];
video = [newVideo retain];
NSData *imageData = [video.allImages valueForKey:#"thumbnailImage"];
UIImage *uiImage = [[UIImage alloc] initWithData:imageData];
smallImage.image = uiImage;
nameLabel.text = video.displayName;
[uiImage release];
}
}
Related
My UITableView, after the messages (content) is loaded into the cells, experiences a very noticeable lag in scrolling and sometimes freezes up for a few seconds. This is weird because all the messages are loaded once the user scrolls. Any ideas on how to make this fast scrolling no problem?
Thank you!
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *simpleTableIdentifier = #"MailCell";
MailCell *cell = (MailCell *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"MailCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
// Anything that should be the same on EACH cell should be here.
UIView *myBackView = [[UIView alloc] initWithFrame:cell.frame];
myBackView.backgroundColor = [UIColor colorWithRed:40.0/255.0 green:148.0/255.0 blue:196.0/255.0 alpha:1];
cell.selectedBackgroundView = myBackView;
cell.messageText.textAlignment = NSTextAlignmentLeft;
cell.messageText.lineBreakMode = NSLineBreakByTruncatingTail;
}
NSUInteger row = [indexPath row];
// Extract Data
// Use the message object instead of the multiple arrays.
CTCoreMessage *message = [[self allMessages] objectAtIndex:row];
// Sender
CTCoreAddress *sender = [message sender];
NSString *senderName = [sender name];
// Subject
NSString *subject = [message subject];
if ([subject length] == 0)
{
subject = #"(No Subject)";
}
// Body
BOOL isPlain = YES;
NSString *body = [message bodyPreferringPlainText:&isPlain];
body = [[body componentsSeparatedByCharactersInSet:
[NSCharacterSet whitespaceAndNewlineCharacterSet]]
componentsJoinedByString:#" "];
body = [body stringByReplacingOccurrencesOfString:#" " withString:#" "];
// Populate Cell
[[cell nameText] setText:senderName];
[[cell subjectField] setText:subject];
[[cell messageText] setText:body];
if ([message isUnread])
{
cell.nameText.textColor = [UIColor colorWithRed:15.0/255.0 green:140.0/255.0 blue:198.0/255.0 alpha:1];
}
else
{
cell.nameText.textColor = [UIColor blackColor];
}
return cell;
}
xCode comes with a profiler called Instruments. It's CPU time profiler is perfect for figuring out which code is slowing things down. Run your app with the profiler and spend a few seconds just scrolling around. It will give you statistics.
Keep in mind, the code inside if (cell == nil) will run about 10 times (UITableView caches just enough cells to fill itself). But the code outside the if is expensive - it runs every time a cell becomes visible.
I would guess the most expensive operations in the code you posted are:
Giving iOS too many subviews to draw on a cell
Do your own drawing instead.
Replacing runs of whitespace in the entire body text with single spaces
The code you posted allocates new strings for each word, plus an array to hold them. Then it allocates two more copies (one with words rejoined and one with runs of spaces compacted). It processes the entire body text string, even if the majority will never be visible to the user in a tiny preview of the body!
Cache the resulting string so that this operation is performed only once per cell.
Also, you can create a new mutable string, reserve space in it, and copy characters from the original in a loop (except runs of whitespace). Instead of processing the entire body text, you could stop at 100 characters or so (enough to fill a table cell). Faster and saves memory.
Slow UITableView scrolling is a very very common question. See:
How to solve slow scrolling in UITableView
iPhone UITableView stutters with custom cells. How can I get it to scroll smoothly?
Nothing seems wrong with your code. I'd recommend using a table optimization framework such as the free Sensible TableView.
I have three different cells. The Cell01, the Cell02 and the Cell03. The Cell01 must appear just one time, at the top of the tableview, and the rest, the 02 and 03 must interpolate (02, 03, 02, 03 (...)).
The problem is that there's some "lag" when scrolling the TableView. I'm loading images from the document folder, and I'm also resizing it to don't require too much processing, but it's still scrolling slowly. It's reusing cells (I checked the if(!cell)).
Here's my code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
int row = indexPath.row;
if (row == 0) {
Cell01 *cell = nil;
cell = [tableView dequeueReusableCellWithIdentifier:#"Cell01ID"];
if (!cell) {
cell = (Cell01*)[[[NSBundle mainBundle] loadNibNamed:#"Cell01" owner:self options:nil] objectAtIndex:0];
cell.someLabel.text = #"First";
cell.someImage.image = [self imageInDocumentsDirectoryWithName:#"mainimage" andSize:CGSizeMake(200, 200)];
}
} else if (row % 2 == 0) {
Cell02 *cell = nil;
cell = [tableView dequeueReusableCellWithIdentifier:#"Cell02ID"];
if (!cell) {
cell = (Cell02 *)[[[NSBundle mainBundle] loadNibNamed:#"Cell02" owner:self options:nil] objectAtIndex:0];
cell.randomLabel.text = #"Second";
cell.someImage.image = [self imageInDocumentsDirectoryWithName:#"secondimage" andSize:CGSizeMake(200, 200)];
}
} else {
Cell03 *cell = nil;
cell = [tableView dequeueReusableCellWithIdentifier:#"Cell03ID"];
if (!cell) {
cell = (Cell03 *)[[[NSBundle mainBundle] loadNibNamed:#"Cell03" owner:self options:nil] objectAtIndex:0];
cell.anotherLabel.text = #"Third";
cell.someImage.image = [self imageInDocumentsDirectoryWithName:#"thirdimage" andSize:CGSizeMake(200, 200)];
}
}
}
- (UIImage *)imageInDocumentsDirectoryWithName:(NSString *)fileName andSize:(CGSize)size
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString* path = [documentsDirectory stringByAppendingPathComponent:fileName];
UIImage *image = [UIImage imageWithContentsOfFile:path];
image = [image resizedImageToFitInSize:size scaleIfSmaller:YES];
return image;
}
Any idea how to improve this tableview (and make it scrolls faster)?
I think scrolling slowly is due to loading image on cell from document directory. fetching images from Doc dir takes some times and when ever u scroll ur table view, a new cell is created and image is loaded from doc dir which takes some time. try to use Lazy loading of image on cell. Also load images in a new thread not in main thread..
There is a sample project of Apple which helps u. lazy loading table view
I hope this will helps u .
Consider loading the images asynchronously. You could keep the references to all the UIImageView in a mutable array, start loading images in an asynchronous block, e.g. using GCD, and then update the image views as they get loaded.
Here's a rough example of how it could look (this assumes you have an ivar NSMutableArray *_imageViews, initialized with the correct size of elements, and filled with nils). I'm coding from the hip here, but I hope you get the idea. BTW, you can fill the mutable array with nils by inserting [NSNull null] into it.
I promise that if you implement this correctly, you'll see a marked improvement in the scrolling speed :)
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
int row = indexPath.row;
if (row == 0) {
Cell01 *cell = nil;
cell = [tableView dequeueReusableCellWithIdentifier:#"Cell01ID"];
if (!cell) {
cell = (Cell01*)[[[NSBundle mainBundle] loadNibNamed:#"Cell01" owner:self options:nil] objectAtIndex:0];
cell.someLabel.text = #"First";
[_imageViews replaceObjectAtIndex:row withObject:cell.someImage];
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^{
UIImage *image = [self imageInDocumentsDirectoryWithName:#"thirdimage" andSize:CGSizeMake(200, 200)];
// because UI needs to be updated on the main thread,
// dispatch yet another block.
dispatch_async(dispatch_get_main_queue(), ^{
UIIMageView *imageView = [_imageViews objectAtIndex:row];
ImageView.image = image;
});
});
}
// et cetera
}
There are two potential performance issues with your current implementation. The first is using NSBundle instead of UINib to load the nib files. NSBundle reloads the nib file from the filesystem each time, whereas UINib reads a nib file once and caches its content in memory. Since it doesn't need to reread the nib from the filesystem each time, instantiating the objects should be orders of magnitude faster using UINib.
So instead of doing this...
cell = [[[NSBundle mainBundle] loadNibNamed:#"Cell02" owner:self options:nil] objectAtIndex:0];
...do this:
cell = [UINib loadNibNamed:#"Cell02" owner:self] objectAtIndex:0];
The second problem is similar; the current implementation is reloading the same images from the filesystem each time instead of caching them in memory and reusing them. To solve this, you could add an instance variable of type NSArray or NSDictionary (depending on how you prefer to retrieve the images), and then check before loading the image to see if it's already in the collection. If not, load the image and store it in the collection before using it. Otherwise, used the cached image instead of loading it again.
So instead of doing this...
cell.someImage.image = [self imageInDocumentsDirectoryWithName:#"thirdimage" andSize:CGSizeMake(200, 200)];
...do something like this:
// Note: Consider defining constants for the keys/filenames.
UIImage *image = [self.cachedImages objectForKey:#"thirdimage"];
if (image == nil) {
image = [self imageInDocumentsDirectoryWithName:#"thirdimage" andSize:CGSizeMake(200, 200)];
[self.cachedImages setObject:image forKey:#"thirdimage"];
}
cell.someImage.image = image;
If you need to cache a lot of images this way, consider using NSCache instead of NSDictionary to help keep the cache from growing too large.
I just finished implementing something similar, and if you make sure that all of the images in the documents directory are already the correct size (200 x 200) then this will work just fine without having to load asynchronously.
If you need the images to be larger, then generate thumbnails that are the correct size when you save the original file, as it actually is taking too much processing to resize the images in "real-time".
In this case though, you only have three images. If you simply cache the image after it has been resized and keep reusing it (instead of making new ones), then it will be even faster than that.
My tableview consists of images loading from server, this slow down my tableview scrolling. Below is my code . any idea, please help me.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
CustomTblViewCellFacetoface *cell = (CustomTblViewCellFacetoface *) [tableView dequeueReusableCellWithIdentifier:#"cellA"];
if (cell == nil)
{
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"CustomTblViewCellFacetofaceNib" owner:Nil options:nil];
for (id currentObject in topLevelObjects)
{
if ([currentObject isKindOfClass:[UITableViewCell class]])
{
cell = (CustomTblViewCellFacetoface *) currentObject;
break;
}
}
}
// configure cell
IStructFacetofaceRequests *objappointmentdetails = [M_ArrFacetofaceRequests objectAtIndex:indexPath.row];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.backgroundColor = [UIColor clearColor];
cell.m_CtrllblName.text = objappointmentdetails.m_strUsername;
cell.m_CtrllblVenue.text = [NSString stringWithFormat:#"Venue : %#",objappointmentdetails.m_strVenue];
cell.m_CtrllblDate.text = [NSString stringWithFormat:#"%# - %#",objappointmentdetails.m_strStartDate,objappointmentdetails.m_strEndDate];
[cell.m_CtrllblName setTextColor:[UIColor colorWithRed:(113/255.f) green:(113/255.f) blue:(113/255.f) alpha:1.0f]];
[cell.m_CtrllblVenue setTextColor:[UIColor colorWithRed:(113/255.f) green:(113/255.f) blue:(113/255.f) alpha:1.0f]];
[cell.m_CtrllblDate setTextColor:[UIColor colorWithRed:(113/255.f) green:(113/255.f) blue:(113/255.f) alpha:1.0f]];
cell.m_CtrllblName.font=[UIFont fontWithName:#"Arial-BoldMT" size:16];
NSData * imageData = [[NSData alloc] initWithContentsOfURL: [NSURL URLWithString: objappointmentdetails.m_strImageurl]];
cell.m_CtrlImgViewUser.image=[UIImage imageWithData: imageData];
[cell.m_CtrlBtnView addTarget:self action:#selector(MoveToNextView:) forControlEvents:UIControlEventTouchUpInside];
cell.m_CtrlBtnView.tag=indexPath.row;
return cell;
}
this is the code i used in cellfor row at index path.
You can solve that by using Asynchronous loading..
please go through this tutorial..
http://www.markj.net/iphone-asynchronous-table-image/
You can use UITableView lazy loading .
here an sample from apple
and u can see this project at github
Yes, UITableView is designed around the assumption of lazy loading. When you make a UITableView, you do not load any of the entries at all. Instead you wait for the system framework to call your cellForRowAtIndexPath method. That method gets called once for every cell that needs to be loaded, and that is just for the cells that are visible at the time. As the user scrolls the table view, new cells come into view, and your cellforRowAtIndexPath method gets called again for each new cell coming into view.
Now that is the general principle. But if your cells are being populated by data from a server, then there are some additional considerations. You could structure your cellForRowAtIndexPath to be as lazy as possible and call the server for each and every cell that comes into view. But the network delays would make the user experience really awful. So it is to your advantage to buffer up a number of cells worth of data ahead of time in a data structure other than the cells in a UITableView. That way, when cellForRowAtIndexPath gets called, you will be able to quickly supply the contents of the cell by constructing it from the buffered data. Exactly how much data to buffer depends on how large each data element is, and what else your application is doing in the way of memory allocation. Offhand, I see nothing wrong with buffering 500 to 1000 cells worth of data in your app. But don't mix up your buffering of the data with the UITableView's queuing and reusing of cells. There is no reason to maintain a large number of cells ready to go - just the data that goes into those cells.
I wonder if anyone can speculate or better yet provide a piece of code as for the implementation of the lengthy friends list in the Facebook iPhone app.
when you open the app and go strait to the friends list, you get the list almost in an instant, at least for me with ~500 friends.
when I try it in my own app it takes lots of precious seconds to populate the table view with the same data, so how does Facebook accomplished such a quick response time ?
upon looking at the tableview in the facebook app you notice there is no scroll bar usually found in such tableview, could that be one sign of the neat trick facebook is utilizing to achieve this rapid rows insert ? could it be they implemented some sort of a virtual tableview with only holds a few dozen rows but rotates them ?
any thoughts ?
the UITableView will let you do this. There are a number of examples on the internet with UITableView and Custom Cell's
Essentially, you load your images in the background, and you reuse the Cells that are in the tableview
EDIT Added example code to demonstrate how this is accomplished.
IMPORTANT NOTE
This code was not tested and may or may not actually function as is.
It was pasted with some editing for length. I did a lot more then this in my app, but in the interest of keeping with the example requested I omitted a lot.
On with the example:
Here is where I get the cell, load it with the items that are readily available. And send it to the background thread to load the rest.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"OfferCell";
static NSString *CellNib = #"OfferItem";
OfferCell* cell = (OfferCell*)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:CellNib owner:self options:nil];
cell = (OfferCell*)[nib objectAtIndex:0];
}
NSDictionary* couponPackage = [self.jsonOfferData valueForKey:#"result"];
NSArray *couponList = [couponPackage valueForKey:#"offers"];
if ([couponList count] >= indexPath.row )
{
NSDictionary* couponData = [couponList objectAtIndex:indexPath.row];
Coupon *coupon = [[Coupon alloc] initWithDictionary:couponData];
NSDictionary *params = [NSDictionary dictionaryWithObjectsAndKeys:cell,#"cell",coupon,#"coupon", nil];
//Right here you would try to load any cached imaged from disk.
//Then send a Thread to the background to load the image.
[self performSelectorInBackground:#selector(loadTableViewCellData:) withObject:params];
//Load up the rest of the custom info into the custom cell.
[cell.captionLabel setText:coupon.name];
[cell.subTextLabel setText:coupon.subText];
[cell setAccessoryType:UITableViewCellAccessoryDetailDisclosureButton];
[cell setCommand:coupon.command];
[cell setParameter:coupon.commandArgs];
[cell setImageURL:coupon.imageURL];
[cell setImageAltURL:coupon.imageAltURL];
[cell setRegistrationCode:coupon.registrationCode];
[coupon release];
}
return cell;
}
as you can see, i call a background thread before i even load the custom content in the cell.
- (void) loadTableViewCellData:(NSDictionary*) objectData
{
OfferCell *cell = [objectData objectForKey:#"cell"];
Coupon *coupon = [objectData objectForKey:#"coupon"];
UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:[coupon iconURL]]]];
[objectData setValue:image forKey:#"image"];
self performSelectorOnMainThread:#selector(setImageOnMainThread:) withObject:objectData
}
after downloading the image, i send a Main thread request to update the Image that is in the cell object.
- (void) setImageOnMainThread:(NSDictionary*) objectData
{
OfferCell *cell = [objectData objectForKey:#"cell"];
Coupon *coupon = [objectData objectForKey:#"coupon"];
UIImage *image = [objectData objectForKey:#"image"];
cell.icon.image = image;
}
##AGAIN This May not Actually Function. ##
I did not copy all of my code for this. this is a hammer out so you can get the idea.
play with the code and test it. but the fundamentals are.
Dequeue the cell that will fit your needs (Reuse Identifier)
Use the cell if it can be dequeue'd or create a new one with a reuse identifier (my example uses a xib file named OfferItem.xib)
Send a thread to the background that will load the image data from disk or url (a combination of both is recommended)
Send a thread back to the UI when you are ready to load the image into the View (Updating the UI must be done on the main thread)
if you can do that, then your friends list (or in this case offers) will be loaded up as fast as possible. and the Images will pop on the screen as soon as they download.
Also if you use a Caching technique it will be faster for subsequent loads because in the the first method {tableView:cellForRowAtIndexPath:} you would load up the cached image immediately.
Aside from that, this should load your cell's pretty fast.
They obviously load the data from a local resource (plist, ManagedObject, ...)
Have a look at some sample code to draw a TableView:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *kCellIdentifier = #"MyCellIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kCellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:kCellIdentifier] autorelease];
}
return cell;
}
The dequeueReusableCellWithIdentifier: thing is one reason why TableViews in iOS can draw quickly. It works somehow like this:
1)You provide an identifier for a cell you're creating.
2)Cells that are visible at first get alloced (with identifier)
3)When a Cell is moved off the screen it gets put on a pile MyCellIdentifier
4)Whenever the system needs to draw a cell of identifier:MyCellIdentifier it first looks whether there are any cells currently unused on the MyCellIdentifier pile. If that's the case it picks one off the pile and thus doesn't have to alloc a new one. That way expensive allocing can be kept at a minimum.
I hope this answers your question :)
I am creating an application which uses a web service.And retrieves a list of users and there details like images, user id and there names.I displayed all the information related to users in table view, Thus each of the cell in the table view has an image with the for tables in it. I am using a Custom cell class to create the individual cells. selecting any row in table presents a detail view (using navigation) which show a larger image and all the details related to the particular user i selected.
in customcell and detail view class i am using web view to display image.
But when i run the app the images gets a bit of delay to display and same happens with the detail view.
Is there any alternative so that i can improve the performance of the table view so that i can have smooth scrolling of table view with out any delay in image loading and detail view??
here is the code...
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CustomCellIdentifier = #"CustomCellIdentifier ";
CustomCell *cell = (CustomCell *)[tableView
dequeueReusableCellWithIdentifier: CustomCellIdentifier];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"CustomCell" owner:self options:nil ];
//cell = [[CustomCell alloc] initwi ];
for (id oneObject in nib)
if ([oneObject isKindOfClass:[CustomCell class]])
cell = (CustomCell *)oneObject;
}
NSUInteger row = [indexPath row];
NSString *imageName = [imgArray objectAtIndex:row];
NSString *completeImageUrl = [[NSString alloc] initWithFormat:#"http://122.160.153.166:201/%#", imageName];
NSURL *url = [NSURL URLWithString:completeImageUrl];
//NSURLRequest *requestObj = [NSURLRequest requestWithURL:url];
NSData *imageData = [[NSData alloc] initWithContentsOfURL:url];
UIImage *image = [UIImage imageWithData:imageData]; /// check to see if we are getting all the arrays such as image array and userId array and name array of same size..
if(image == nil)
{
}
cell.imgView.image = image; /// other wise an execption of out out array range will be shown
[image release];
[imageName release];
//[cell.webView initWithFrame:CGRectZero];
//[cell.webView loadRequest:requestObj];
//cell.webView.frame = CGRectMake(20, 0, 80.0, 64);
cell.userIdLabel.text = (NSString *)[userId objectAtIndex:row];
cell.nameLabel.text = (NSString *)[userName objectAtIndex:row];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
return cell;
}`
i think problem can be in imgArray array as i am setting it from other class. Where i request the web service and fetched all the data about users .
Any help is greatly appreciated . Thanks in advance
I got the same problem. For that I used EGOImageCache and some thing.
Find this Url for EGOImage
Download files those names starts with "EGO", and add those to your project.
and write the following code where ever you want to put the image:
EGOImageView *imgView = [[EGOImageView alloc] initWithFrame:CGRectMake(50,50,220,360)];
NSString *imageName = [imgArray objectAtIndex:row];
NSString *completeImageUrl = [[NSString alloc] initWithFormat:#"http://122.160.153.166:201/%#", imageName];
NSURL *url = [NSURL URLWithString:completeImageUrl];
imgView.imageUrl = url;
[self.view addSubView:imgView];
Thats it. Use the similar code, where ever you want the image.
At the first time while loading it will take some time to download the image. But later it will cache the image and use it the next time.
Is there any alternative so that i can improve the performance of the table view so that i can have smooth scrolling of table view with out any delay in image loading
For this the answer is Lazy Loading of images in cells
You can implement lazy loading on webviewDidLoad which shows that webview has loaded completely
Using a UIWebView to display a single image is overkill. You should be using NSURLConnection (or one of many alternative HTTP wrappers/libraries) to load the image data and UIImageView to display it in each of your table cells. In my experience, there is no way (or at least no straightforward way) to eliminate the rendering delay when using UIWebView.
Why are you using the webview for displaying the images. Imageview should be used instead. If you are getting the images from the server then you should get those in separate thread and after you receive the images you should reload that particular row.
Some code snippet is like this:
- (UITableViewCell *)cellForRowAtIndexPath:(NSIndexPath *)indexPath
...
...
UIImage *img = (UIImage *)[imagesArray objectAtIndex:indexPath.row];
if(img == nil){
[imgView setImage:temporaryImage];
[NSThread detachNewThreadSelector:#selector(getTheThumnbails:) toTarget:self withObject:indexPath];
}
else
[imgView setImage:img];
for further assistance look at this
Hope this helps.
Thanks,
Madhup
okay finally i removed the uiweb view from my app and used Imaged view and succeed.
i used the link that was given by the developer of the tweetie . here it is link text
i used the ABTableViewCell class and created the whole cell using the code.
The scrolling was very jerky when i executed the app. after applying almost 4 hours and with the help of lazy loading i was able to run my app smoothly. I stored the data which is retrieved from url into an array then applied the concept in tableView:cellForRowAtIndexPath:
method..
Thanks you guys for helping me ...
Three20 has a rich-text table view cell class (TTStyledTextTableCell I think) - should render significantly faster than an embedded UIWebView. You could also roll your own, though that would take a lot longer.