How to display a grid of more than 1000 thumbnails as ui views in UI Scrollview with smooth scrolling - iphone

I have to implement a application which displays a grid view of thubmnails each of which is a clickable object. The grid view will display 2 images( which i suppose can be a uiview). And 4 rows per page.
The use should be able to smoothly scroll through the image grid view. The images for the thumbnails will be fetched from the url i get from server. However assuming i have the urls in my model how can i implement this feature to display them.
Few problems i have encountered are:
All the images(UIviews) cant be loaded due to memory constraints. Hence paging can be enabled.
On implemented paging using uiscrollview delegate the ui becomes irresponsive for some time. I am downloading the images in a NSOperation queue and posting the image on mainthread for displaying on screen.
I want the scrolling to be very smooth without jerky feature.
How can i implement this?
TIA,
Praveen S

I was having a similar problem.
What i did was at an instance i kept only 3 pages(or screens with 4 rows as you said) in the memory and cleared remaining all.
If suppose there are 3 screens s1, s2, s3. And the user is viewing s2. Whenever he scrolls to s3 i will remove s1 and load a new page s4. So that at any point of time there will be 3 screens only.
And the users will have a better experience. And also less memory will be occupied.

Related

UIScrollView paging works fine in simulator but application crashes in device after 15-20 pages

I have used UIScrollView with paging enabled. I have more then 1000 images and I am adding 12 images per page. I am loading 12 images every time when page is scrolled. But after scrolling 15-20 page application is getting crashed in device. It works fine with simulator. Please let me know what can be the issue ?
Thanks in advance.
You didn't provide any code but it looks like this is a case of bad
memory management, as all the comments suggest.
One way to solve this would be to allocate just three pages (each holding 12 images)
and then joggle with their positions and contents according to user interaction.
I think you'll find these two links helpful:
Creating Circular and Infinite UIScrollViews
UIScrollView Infinite Scrolling

How to get rid of the hitch when lazy loading pages of a UIScrollView

I tried to implement the lazy loading solution for UIScrollView with paging enabled, as in the PageControl example from Apple. It seems to work fine, the only problem is that as the user scrolls past the 50% of the page, there is this short hitch as the content of the next page is loaded (obviously because loading the next ViewController takes some time and it seems to happen on the main thread).
Is there some way to make the scrolling seem more smooth that would work no matter how fast the user scrolls ?
You need to make sure that anything which takes time happens asynchronously. The techniques for this will vary based on what kind of content you're loading or what sort of drawing you're doing that causes the delays. Try to load images in the background, do custom drawing in the background, use operations or gcd to break up large tasks into smaller chunks that can happen concurrently, etc.
You should be lazy loading the surrounding pages so that they're already loaded when the user scrolls.
So if the user scrolls to page 2, load pages 1 and 3 (if they aren't already)

UIScrollView Lazy Loading Strategy With a Twist

I have a horizontally scrolling UIScrollview with paging enabled. Each page represents a data feed. Each data feed consumes a fairly large amount of memory including text and images displayed in a UITableView. Since the user can have an unlimited amount of data feeds, I need to lazy load them to prevent maxing out my memory usage. My thought is to keep up to 5 data feeds in memory at any given point, and release anything outside of that range. My initial take is to keep the page in the viewport in memory, and the 2 pages to either side of it. This way when the user scrolls, the next sequential page will always be in memory and will display quickly.
Here is my problem:
We also need to support a scenario where a user can skip to a specific data feed, possibly 10 or more pages to the right or left, which throws my entire lazy loading scheme out the window.
Might there be a better strategy to support this scenario?
Yes, what you can do is create an outer scroll view, which houses individual cells akin to a tableview. In this respect, the cells have a content view which you can place your data, let's just assume you know how to do that since it seems you do.
Once you have this architecture in your mind, it becomes fairly clear: You can, knowing the width of your cells, and the size of the screen, some simple math can tell you how many you have on screen, and you can add one to the left or right so you're preloading some data for when the user scrolls.
This will say, give you the ability to have in memory, at most 5 feeds, if 3 are visible, at the start or end of the content view in the scrollview, 4 feeds, regardless of whether or not you have a billion feeds.
One critical part of this is cell reuse. You maintain a couple NSSets, one for recycled cells, and one for visible cells. Add items that have gone off screen to the recycled cells, dequeue items from recycled cells when setting up the cell, as to save additional memory allocations, which can be expensive. Just remember, using this strategy, you are still subjective to the same caveats as a UITableView with respect to cell reuse.
I'm plugging some software I wrote here, so forgive me for that, but I'm doing so as an example of what I'm talking about if you get stuck implementing what I discussed here, it's available here for your perusal.
One final note. To support skipping of cells, it's just simple math again to adjust the point in the scrollview you are at. The action for this can be done with a gesture, though now we're talking a pan gesture recognizer, with some specific properties that will be specific to your application, as an example. Or you can use buttons if you really must. Just ensure you know how to calculate your offsets to your cells, and scroll to that point. You'll be fine.
It's hard to give accurate advice with the information provided in the question. So I will just present a few thoughts I got when reading the question.
Does it take long to download a feed? Would it be possible to just download a few item (a screenful) to get the first few items showing right away? Perhaps lazy load the images if possible.
Have you considered caching the feed data on disk? That way you can present some data right away and then update the feed as new data gets downloaded.
Since each page is a feed view, would the user just scroll past a feed without looking at it? Do you really need to load 2 views on each side or can you get away with just 1 view on each side.
I don't think your lazy loading scheme stops working just because the user can skip directly to any page. You would have to start loading the data for that page when it is selected but by using a disk cache or downloading a small sample could make the app feel faster. I also think that using some kind of animation to animate to the selected page could buy you a little time.
Here is my problem: We also need to support a scenario where a user can skip to a specific data feed, possibly 10 or more pages to the right or left, which throws my entire lazy loading scheme out the window.
Then you need to fix your data structure. I wrote pretty much exactly this (a UITableView-like paging scroll view) and it works fine (there are some reloading quirks, but hey...).
Keep track of which pages you've loaded. I used a ring-buffer-alike modulo 8 and spent a while getting the code right; it's probably a lot easier to just use an NSDictionary with NSNumber keys and UIView values. This means when you change from page 1 to 10, you can still tell that the loaded views are for pages 1, 2, and 3, and drop them.
Load the required pages in -layoutSubviews. I would load 1 or 3; 5 is probably too many (but you need to load at least 2 if you're between pages).
Load 3 (one to either side) in -scrollViewDidScroll:. This is so that when you scroll from page 1 to 2, it doesn't try to load page 4 (which hasn't been loaded yet).
Load 5 (two to either side) in –scrollViewDidEndDragging:willDecelerate: if willDecelerate is NO, –scrollViewDidEndDecelerating:, –scrollViewDidScrollToTop:, and –scrollViewDidEndScrollingAnimation:. The idea is that the animation's over, so you can load the extra views without the user perceiving lag.
Possibly load 5 in –scrollViewWillBeginDragging:, to make sure that page 3 is loaded if you're currently on page 1.
I decided to do "two pages either side" because when you flick from page 1 to page 2, it often shows a pixel-wide sliver of page 3 when it bounces. This can be avoided with scroll view insets, but we didn't think of that at the time (oops). There's otherwise not that much of a reason to choose 5 over 3.
It's a bit of work to get right, but otherwise seems to work flawlessly.

App like default photo browser in iphone?

i am developing a app which contains feature like default photo browser in iphone. I done some what similar to that. but after loading some(near about 10-15) images from remote server,i am receiving memory warning.My requirement is loading image one by one. For this, on scroll view i am putting an images and increasing the contentSize of scroll view. it will work fine. but due to memory warning app quite.
Guys, any have any idea to approach for this feature which work similar to photo app without problem?
thanks in advance .
You're running out of memory because you're keeping the data for 10 or more images in memory at one time. You need to have more logic in your code that not only preloads and increases the scroll view's content size, but also removes UIImageViews from the scrollview (and thus from memory) as the user scrolls to newer stuff. (You can also save "evicted" images to the cache area on disk so if the users scrolls back you don't have to go to the server again.)
If you use a UITableView, it will request the images only when needed, and will automatically purge off-screen cells to save memory. It may not fit into the aesthetic for your application, though.

Image Caching Problem in iPhone

I have briefly described the working of my application to under stand my Question.
I have an application, in which more than 1600 images are stored with in iPhone-Application-Document Directory.
I have a tableView on Main Screen as follows.
=>First Category
=>Second Category
=>Third Category
=>if user selects First category, Images are loaded in my ScrollView
Like
|--------------------Page View Controller-----------------|
| First Image | Second Image | Third Image | Fourth Image |
|--------------------Page View Controller-----------------|
After selecting Category, User can see - First Image From Page view Controller & others are already loaded in page View Control, user has to just scroll left - right to see the other images, but at a time user can see only one image.(that is the task of page view control)
Now Each Page has an Image View Placed in Scroll View (so user can zoom in out)
All this things work Perfectly,
Problem occurs in following situation.
=>After watching first category's images
=>User presses Back
=>Now user selects second category to view all images of second category are loaded in page view controll.
iPhone terminates the application in the given situation. (as it can't load all images to page view control)
(each image is of at-least 4 MB approximately.)
iPhone simulator works perfectly in described situation but iPhone doesn't.
iPhone terminates the application in given situation.
I think there might be memory caching problem in iPhone.
Question is how to resolve this problem?
Thanks in advance for helping me.
You are having a memory problem, you need to manage your pictures better, release them from memory when not in use. For your scroll view dont load all images at once, load at most three, this is all you need, the reason i say three is because youll have something like this
PIC ActivePic Pic
or
ActivePic Pic - here you only need 2
You load picture on each side of the active picture so when the user scrolls clipping does not occur. When you are not in the scroll view make sure to release all the images if not ull run out of memory like you have been expiriencing. Look at the sample project PageControl here http://developer.apple.com/iphone/library/samplecode/PageControl/, here they manage t he views of the scroll view in the same fashion described above.