When I scroll to new area of the UITableView with lazy image loading, then
immdietly scroll back to the old area, no matter what I do now, the new area will not show new images.
My code is based on apple lazy table view.
Till now I thought it was something with the web server, but I had cache functionality now, and all images are loaded from iphone files, so for sure there is somthing wrong in my code.
Again, the images are not shown ONLY in that case :
UITableView is loading the data
All visible cell are showing the images correctly.
If I scroll to new area, move to old area *quickly* and move back to new area the image will not load, no matter where I scroller now(only the images in the new area that I quickly scorll back from will not load)
all on other cases, the images are shown correctly.
Without seeing the some code its hard to say. If your display is tied to a callback from the NSURLConnection you might be losing your reference to the delegate.
When you scroll the cell view get repopulated with the data in the new cell. If the NSURLConnection is running outside of the cell view you might be losing the reference to it's delegate. When the NSURLConnection is completed if it doesn't have a delegate to fire the complete method then it won't get called. When you scroll to the new cell the NSURLConnection is already complete so it doesn't call the completed again and the spinner just keeps going.
I fix it. the bug was nothing to do with all above. so nothing to share and learn from.
I thought it is important for other I'll be clear about that, so no one will be confused about what I wrote earlier.
The process of checking if image already download was wrong.
Related
I have a UITableView that contains several cells and some of them (the ones for files that are still uploading) have both an UIActivityIndicator and an UIProgressView. The ones for files that are finished use a different icon (instead of the activity indicator) and hide the progressview.
This table is using a NSFetchedResultsController as data source, so I get the updates on the data model and update the content.
Everything works just fine. The problem, however, is performance. Every time I call reloadData my UIActivityIndicators flicker, and it's not very smooth. Although I'm caching from the nib file, reloadData will have to calculate the new progress % for the ProgressView and I don't do anything with the ActivityIndicator other than hiding it if upload is complete.
Anybody ever tried something similar? Is there a workaround?
I was thinking about having an array of my progressview references and use that instead of calling reloadData.. not sure if this is the correct approach.
Thanks,
Fernando
When you call reloadData on the UITableView, all the cells of the table view are completely refreshed, re-assembled and redrawn. All the old ones are thrown away. This means that all the subviews of the UITableViewCells are removed and re-created too (including your UIActivityIndicator and UIProgressView). The refresh causes these views to flicker, or perhaps jump back to their start state. As there is no way of setting the frame of a UIActivityIndicator, your suggestion of restoring some progress value simply isn't possible.
Instead, perhaps you should try and engineer your "refresh" to not require a complete refresh of the table? For example, if you want to change the text of a UITextField within the view, you could simply access this text field and set the text property (no refresh is required). Or, if you want to hide your progress indicators, you could go into the appropriate object instances and set their property. You should design your app so that this is possible. Making changes this way avoids having to reload cells from scratch.
Besides the benefit of fixing your problem, using this method of updating, you should also see a large performance increase. reloadData is a very costly method to use and should be only used if it is absolutely necessary to really re-create the entire UITableView from scratch.
Hope this helps. :)
I am working on an iPad app that lets the user scroll through a number of images (usually around 20 .jpg files in a single horizontal scroll view). The file sizes are around 200 kb each. The images are set as the "Background" property of a UIButton because I wanted to allow the user to click the button to save the image. Every time I run the app, it crashes after scrolling for a little while. If you don't scroll, it behaves normal. I did run the app using the performance tools and didn't find any leaks.
I am getting a "Level=1" memory warning just before the app crashes. I had it running with about 8 images in the scrollview and never had a problem. So I know it has something to do with the scrollView and the images/buttons. In the "viewDidLoad" method, I simply did the following to set up the scrollView and then linked it in Interface Builder:
[scrollView setContentSize:CGSizeMake(5722, 340)];
[scrollView setScrollEnabled:YES];
[scrollView setDelaysContentTouches:YES];
Any ideas on how to get this to work? I added the images directly to the button in Interface Builder. Would it help if I deleted the background image, and instead set the backgrounds in the "viewDidLoad" method? Any help would be appreciated.
Sounds like what you need to do is create individual cells that these images live on, that get recycled like you'd get in a tableview. I have some code which does this that you may use for your purpose, or at least give it a go anyway. Works just like a tableview.
It's available here. This does the heavy lifting for you already, in that all you need to do is create one of these, slap it in a view somewhere, and create your individual cells. Those cells will be reused as you scroll so you won't need more than N + 2 cells loaded into memory at any one time, where N is the number that fit on your screen.
as jer wrote, the problem seems to be in the recycling. Make sure to remove, release and update the content of each cell every time you get a new one in tableView:cellForRowAtIndexPath:
(I would have commented jer's post but I'm unable to do this, probably because of my limited permissions).
It's been more than 3 years since Cocoa-Touch is out, the licensing is permissive now.
Many, many apps have UIImageViews that are actually buttons, and load from the internet.
Is there any open UIImageView subclass (or similar) that supports:
adding a target for the touchUpInside event (maybe others too)
initializing with a NSURL, loading the image from that URL (async ofc) and displaying a UIProgressIndicatorView while loading
Or is everyone pretty much rolling their own for this?
It seems to be such a common thing, yet google has no good hits.
You wouldn't want the UIImageView derived class to load its image--especially if it's in a table view because when the user scrolls the table view, the image that will display in the image view would need to change. If you are assigning a specific image to a specific image view within a table view, you run the risk that the image displaying will be out of date by time the image data has actually returned.
While I wouldn't call it trivial as Daniel said, I would say that it is simple enough that you could probably code it up fairly quickly. The idea though is that you want to have some other class, a singleton perhaps, that handles all of your image download requests and then notifies your view that contains your image view that the images are available when the requests complete.
You should also consider that you can set an image for a UIButton, so then you wouldn't need to derive your own UIImageView if all you need is -touchUpInside. You could create an action for the button and implement it pretty easily.
I was wondering, what would be the best way, to implement an 'extra' scrollbar, showing thumbnail versions of the pages, you are currently viewing.
In my case, I would like to have maybe around 20 images, which I would animate with Cover Flow Layers and while I 'scroll' up an down to view them, a scrollbar appears at the side, showing the smaller thumbnail versions of all the pages while the thumbnail currently visible is rendered slightly highlighted.
Is there anything specific I need to keep in mind? Thanks in advance for any ideas!
You are not giving much info to work with:)
Build a UIScrollView and a UIView, stick all the thumbnails into the UIView, stick the UIView into the UIScrollView.
If you have a lot of images, consider loading them in as "dummies/blank image" and have an NSOperation load them in the background. Consider releasing images that are outside of the screen, so that if 3-7 is on the screen then you only load in 2-8 and release everything else.
Regarding the logistics of it:
Build a viewController for holding everything. Then build a thumbnail viewController "component" that has a delegate method for setting the "displayed" image and maybe one for scroll and click.
Build a FullSize viewController component for handling the full size images. Have that also implement some delegate methods to communicate to the top most viewController. Add the two components to the top viewController, hook up the logic and you are done.
Make sure there exists only one model array/dictionary in the top most viewController and "feed" that downwards to the thumbnail and fullsize viewController, when some one clicks or scrolls, inform the top most viewController and have that update the other viewController.
Was that the kind of answers you were looking for?
:)
I'm developing on the iPhone and I have seen in the AppStore that the images are progressively downloaded in the UITableView... How can I implement that?
My idea was to detect the showed content (which cells are shown) and download these images. My problem is that I don't know how to detect the showed cells!
Is it the good way to do it?
Best
The way this was demonstrated at the iPhone Developer Tech Talk was to use NSOperation and NSOperationQueue.
The idea is to wrap up your image download request (using NSURLRequest) into an NSOperation.
You can set your cell as the receiver of a call back sent by your operation when it's complete so that you can attach the image to the cell (draw it manually, or add it to an image view).
Then basically, in your cellForRowAtIndexPath method, tell the cell to start the image download, and have the cell create an NSOperation and add it to the operation queue managed by your table view controller or something.
The queue will start executing the operations and call back to each cell when they're done.
If you want to, you can cancel the operation if the cell moves offscreen, so you don't waste resources downloading an image that will be thrown away because the cell won't be visible to display the image.
Here's an example of how to do this that implements the basic idea that Jasarien talks about. It may be sufficient depending on your application's needs and is generally good example of how to do it if it isn't.
I would implement each cell as a subclass of UITableViewCell and then override willMoveToWindow: method in the subclass. willMoveToWindow: is called when the cell view becomes visible on the screen or when it goes off screen (newWindow gets nil). Then each cell can queue a request to load its image as it becomes visible (and maybe even cancel its queued request if it goes off screen).
BTW, You can use the visibleCells property of UITableView to get the list of cells that are visible.
#Jasarien: nice answer
Or you can use the three20 project if you want. there is a TTTableViewController that already handles all the stuff you want. you only have to input the URL to the imageview and viola.
TT also caches your images in memory or also on disk.
check out the sample project bundled in three20 gitbub ressource. there an example.
That is calles LazyTableView...You can gt tutorial from here
http://developer.apple.com/library/ios/#samplecode/LazyTableImages/Introduction/Intro.html
Please go through this link , and try to integrate Lazy table view load , you can achieve you output , http://www.cocoaintheshell.com/2011/05/progressive-images-download-imageio/ change the url in ProgressiveImageDownloadViewController in Download button click method.