2

I am creating a application which displays 8 thumbnails per page and it can have n pages. Each of these thumbnails are UIViews and are added to UIScrollView. However i have implemented Paging using the Apple sample code.

The prob:

  1. Each thumbnail(UIView) takes 150 millisecs to be created and added to scroll view
  2. Hence for 3 pages it takes awful huge time to be created and added to the UI Scrollview.
  3. At this point the scroll view is not very respsonsive and it is very jerky and gives a bad user experience
  4. How can i create the thumbnails and add them to UIScrollview without affecting the touch responsiveness? I want them to run independent of the main thread which is resposible for handling touch events (i suppose).

Also i would like to mention that when a thumbnail is created i trigger a Async download of the image and the delegate method is called when download is complete.

Let me know the the options i have to make this more responsive and update UI without affecting the touch operations. The page control works fine with lazy loading of the grid of thumbnails.

TIA,

Praveen S

toasted_flakes
  • 2,502
  • 1
  • 23
  • 38
Praveen S
  • 10,355
  • 2
  • 43
  • 69
  • This is what happens when you post the same question twice. People start voting to close both questions as duplicates of each other, and they both wind up getting closed. – Robert Harvey Feb 27 '11 at 23:32
  • Hey it was problem with my internet and hence i wound up posting the question twice before i could see the prev update. Will be carefull henceforth. Looking forward to a good solution. :-) – Praveen S Feb 28 '11 at 05:36

3 Answers3

10

Grand Central Dispatch is easy to use for background loading. But GCD is only for after iOS4. If you have to support iOS3, performSelectorInBackground/performSelectorOnMainThread or NSOperationQueue are helpful.

And, be careful almost UIKit classes are not thread-safe except drawing to a graphics context. For example, UIScrollView is not thread-safe, UIImage imageNamed: is not thread-safe, but UIImage imageWithContentsOfFile: is thread-safe.

dispatch_queue_t mainQueue = dispatch_get_main_queue();
dispatch_queue_t concurrentQueue =
    dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

dispatch_async(concurrentQueue, ^{

    dispatch_apply([thumbnails count], concurrentQueue, ^(size_t index) {

        Thumbnail *thumbnail = [thumbnails objectAtIndex:index];
        thumbnail.image = [UIImage imageWithContentsOfFile:thumbnail.url];

        dispatch_sync(mainQueue, ^{

            /* update UIScrollView using thumbnail. It is safe because this block is on main thread. */

        });
    }

    /* dispatch_apply waits until all blocks are done */

    dispatch_async(mainQueue, ^{
        /* do for all done. */
    });
}
Kazuki Sakamoto
  • 13,929
  • 2
  • 34
  • 96
  • For an example of this in action, people should refer to the [WWDC 2010 session video](http://developer.apple.com/videos/wwdc/2010/) 206 "Introducing Blocks and Grand Central Dispatch on iPhone". They show a demo of just this kind of background image loading using GCD. – Brad Larson Mar 01 '11 at 15:13
  • I also wrote an answer for [NSURLConnection and grand central dispatch](http://stackoverflow.com/questions/5037545/nsurlconnection-and-grand-central-dispatch/5151402#5151402). It would be helpful. – Kazuki Sakamoto Mar 01 '11 at 20:28
0

I was having a similar problem.
What i did was at an instance i kept only 3 pages 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 the users will have a better experience. And less memory will be occupied.

SNR
  • 1,249
  • 2
  • 20
  • 38
  • I am not worried about the memory as i am also keeping 3 pages in memory. However the elements of each view take lots of time to be created and hence the responsiveness is low. – Praveen S Feb 28 '11 at 05:33
  • Then the only way is to use a activity indicator while the images are loading. ;) – SNR Feb 28 '11 at 06:49
0

Whether you are using a subview or a separate ViewController for each "page" or element of the Scrollview, the jerkiness or poor performance can be helped by changing the location of your code.

Specifically the apple sample code for a scrollview with pagecontrol has something like this:

[self loadScrollViewWithPage:page - 1];
[self loadScrollViewWithPage:page];
[self loadScrollViewWithPage:page + 1];

However, that code appears in their sample in the method "scrollViewDidScroll". It's trying to do multiple heavy lifting by both scrolling and loading at the same time. Even if your images are local this is nasty.

If you move this and related code including a reference to the current page to "scrollViewDidEndDecelerating" the jerkiness of the interface is resolved because the loading happens while the scrollview is no longer moving.

tester1
  • 61
  • 1