You can now release the image and receivedData because you passed them to the methods, now after setting the image of imgView there is no need for the image or receivedData objects.
I don't understand why you are creating a new imageView everytime a new cell is created. Don't you miss adding it to the cell as a subView or something like that?
so how would you change the image on every cell? because table view will reuse the image initially created with the cell...
Ok, here's how I would do that:
Create an array of all the different URLs for the different cells.
Create your default cell in the if (cell == nil) part.
Right after that part you configure it. So try to get the URL for the row (indexPath.row) of your URL-Array.
cell.image = theImageCreatedUsingTheRightURL;
basically that's what i am doing... but it seems like for every scroll table is re-reading data from url and then creating image. i checked and found that reading the data from internet is most sluggish part.
only another way i found to do is, load all images before loading the table. then get the image (instead of url) for each cell. That works well for the scrolling, but my concern is 1) loading take pretty long 2) why load all these content (table may have 20-50 rows) if user does not need to scroll down?
So you need a way to load the image when it's the first time it is showed but after that it shouldn't load the image again...
The best way I can think of is, as you mentioned, loading all images before it begins showing them.
hmm, that didn't work... it's reusing same image for most of the cells... maybe i need to create a matrix for rows with images and url values...
damn, finished four packs of red bull with this issue already! Thanks for sticky up bro.
I wonder how Apple did this in their App store application and iTunes application. It is so smooth, and if you notice, you will see text data loads the entire table initially, but images loads on demand for only current visible rows... neat. i want it!!!!!
Yeah it's like "load while beeing in background".. Great that I never want to do something like that, but keep us updated if you find something, or let's hope there's someone else who has some ideas
Isn't that possible via a seperate thread? (I don't know that just something that went into my head..)
i would say threading is the key as well. main thread loads up the cells text.. once complete runs down all the images. i believe they only ever show 25 or so at a time until you click the 'show more' link.
__________________
---------------------------------------------------------------------- I love being a dad, flying airplanes and writing code.
----------------------------------------------------------------------
Follow me on Twitter: @BostonMerlin
Feed your brain on Twitter: @iPhoneDev101
----------------------------------------------------------------------
iPhone Apps:
I tried threading, didn't see any result. If you see apple's App Store, they don't do "Show More" link... all hundreds of rows are drawn at once... still you have smooth scrolling. I am dying to know how they do it, specially how images are only loaded for the cells that visible!!!
Ok guys, I just found the solution!!
after reading the documentation, i found that there is delegate method called:
– tableView:willLoadVisibleCellsInRowAtIndexPaths:
This method along with visibleCells property will do the trick to only load images for the cells that is currently visible!!
HOWEVER... It seems like codes inside this method is not executing. I tried using NSLog() to check. Also, I can't find this method in my iMac's XCode's documentation, but I can find it in MacBook Air's installation of XCode! wired. both has iPhone SDK 2.0 installed.... any idea?
Is this delegate method part of SDK 2.1? but my Air's Xcode documentation is part of 2.0 and declared in UITableView.h file.....
Did you get the solution? I am also looking for this. How can we use threading? I mean, if we use one thread to dowload the images, if one image is ready can we notify the table?
yes, you can notify the tableviewcontroller once one image is downloaded. alternatively, you can also put each image download to NSOperation or NSInvocationOperation. google with these two keywords, you will know what to do.
There are many ways to do that. Preferred way to do would be to define a delegate in your application with method name that will be called after download is finished, say:
Code:
-(void)downloadDidFinish:(id)data;
your tableview controller need to conforms to the delegate which in turn will basically call tableview reload method each time delegate method is called.
now, when you are calling the thread (NSOperation or NSInvocationOperation, or any standard NSThread), you pass the delegate object in the parameter, which is self variable. so after thread task is completed, the thread will call:
Hi, thanks a lot for your help.
Another question:
Do you have willLoadVisibleCellsInRowAtIndexPaths working?
I could not find the function in the documentation, I think we can use tableView:willDisplayCell:forRowAtIndexPath.
There are many ways to do that. Preferred way to do would be to define a delegate in your application with method name that will be called after download is finished, say:
Code:
-(void)downloadDidFinish:(id)data;
your tableview controller need to conforms to the delegate which in turn will basically call tableview reload method each time delegate method is called.
now, when you are calling the thread (NSOperation or NSInvocationOperation, or any standard NSThread), you pass the delegate object in the parameter, which is self variable. so after thread task is completed, the thread will call:
The following is what I want to do, could you guys help to review it, thanks a lot.
I will define the following members in the TableViewController class:
NSMutableArray imageArray ;
NSMutableArray urlArray;
UIActivityIndicatorView activityIndicator;
1.
cellForRowAtIndexPath
{
…
[activityIndicator startAnimating];
cell.image = imageArray[imageIndex]; //initial state for image will be [UIImage imageNamed: @”blank.png”];
}
2. willLoadVisibleCellsInRowAtIndexPaths
{
[self performSelectorInBackground:@selector(getImageData ) withObject:imageIndex];
4. getImageData
{
// a. get url from urlArray by imageIndex
// b. get imageData using CGImageCreateWithJPEGDataProvider or NSURLConnection to get the imageData
// c. Update imageArray
[self performSelectorOnMainThread:@selector(didFinishDow nload: ) withObject:data];
}
PS: 1) I did not use a seperated delegate
2) Need to make sure willLoadVisibleCellsInRowAtIndexPaths is working
few points:
1) performing background selector in the same controller instance is bit scary. This will put the controller into multi threaded mode. you just have to be little extra careful what variables you use and might need to put @syncronize block or have locking machanism.
2) I confirmed with Apple engineer, that willLoadVisibleCellsInRowAtIndexPaths does not exists any more. It used to in beta version, but has been take out in the final. I asked him way, he does not know. Instead you can use visibleCells property to determine which cells are visible at given point
Instead you can follow this pattern:
1) at viewDidLoad, you start that network activity indicator or the activity indicator view, and send request to the background thread for ALL image downloads (not only for the visible rows)
2) at cellForIndexPath you intialize the image with @"blank.png"
3) when background thread send didFinsihDownload message to the main thread, you perform tableView reload.
so user at first get table cells with text and empty image. as soon as image download is completed, images will be reloaded for the visible cells automatically.
I just checked the facebook app and pictures for user and other pictures only gets loaded when they become visible.
I only noticed now that the table view only load tableviewcell when they are displayed. Maybe downloading in an other thread images in an NSDictionnary with keys corresponding to rowIndex may be the solution?
1) I do not see the differences between delegate and method in the same controller, if we use delegate, the controller should adopt the protocol, there will be multithread too. Please correct me if I am wrong.
2) visibleCells or indexPathsForVisibleRows? I think we need call them in imageData collecting thread, but how can we know the visibleCells change so that we can trigger the thread to start download new data?
3) Unfortunately we still need visibleCells to display the visible cells when they are ready. You can have a look of Big Canvas PhotoShare at App store, Recent Photos, that is what I need.
Thanks a lot.
Last edited by victor_zzm; 08-15-2008 at 01:48 AM.
difference is that you are not making the controller instance as part of new separate thread. instead you start a thread on new class instance. delegate methods will be used only to call the notification method in main thread, so controller class is not part of the new thread. This info was given to me by the Apple engineer when i used a support ticket and was dealing with these issues.
hi all!
i m facing the same issue, i want to create an appliaction, that require me to load the text in the table cell first and then load images.
unable to do it properly, facing the same old smooth less scrolling issue.
If u guys have figured out some way, please do paste the code, that will be of great help for new codes like me.