2

I need to show a paginated slideshow of moderately DOM-intensive HTML pages in an iPad application.
All documents are tailored for iPad screen so there is never any scrolling inside UIWebViews.

I decided to put UIWebViews inside UIScrollView for pagination.
It works really well and smooth after all web views have rendered their content.

However, I can't afford waiting for 20, 30 or 50 web views to load before user can scroll: it takes minutes.
I tried to anticipate swipes in scrollViewDidScroll handler and pre-load a few next pages as user keep scrolling.

This worked much better (no performance difference between 10 or 150 web views).
However calling loadHTMLString in scrollViewDidScroll handler causes scrolling to lose it smoothness.

I don't care if it takes a second longer to show a particular UIWebViewβ€”all I want is for scrolling to be smooth and available as soon as possible, and to lazily preload UIWebViews on the go.

How do I achieve that?

Dan Abramov
  • 264,556
  • 84
  • 409
  • 511

1 Answers1

1

This is a difficult problem and there is no easy/elegant way to solve it.

One way to speed up the scroll would be to lazy load the pages as you stated in your question. However, in order to ensure smoothness you would have to control when the loading happens.

So say you began by loading the first 5 pages on initial launch. When the user scrolls to page 2 and STOPS, you begin loading page 6. As soon as the user starts scrolling again you pause the loading only to resume when they have stopped on a new page. Pausing the loading in between will help smooth out the scrolling. Also, make sure you release data when possible because it can build up and hinder smooth scrolling down the line.

Another option would be to have the UIWebViews begin loading only as soon as the user stops on the page. So say I scroll to page to, once the scrolling stops I begin to load the HTML. This is not as "pretty" as the first options but it will ensure that the scrolling is smooth.

Another option, this one is a bit out there, is to run through and load all the HTML pages rich text. Leaving out all the DOM intensive stuff. Then grab a screen shot of those semi-loaded page using this method. When the user stops on the page you load it all the way including the DOM intensive stuff. This will let the user feel as thought they are scrolling quick with everything loaded.

Here is a great scrolling class that I have used before.

Here is some code to help with method 3.

Good luck and I hope that this helps!

EDIT: Here is a great post from the guys at LinkedIn on how they solved webView scrolling problems. It would be worth a read.

Community
  • 1
  • 1
random
  • 8,568
  • 12
  • 50
  • 85
  • Thanks for your time. I didn't realize I can *cancel* loading HTML. I'll try this now. – Dan Abramov Jul 16 '12 at 19:51
  • I just tried calling `stopLoading` when user begins a drag, and while it got noticeably better, it's still very far from seamless. The problem manifests itself when user scrolls *right after* we think it's safe to load the content. Scroll event gets queued, and we have no way of knowing user's intention to scroll before load is finished. – Dan Abramov Jul 16 '12 at 20:05
  • Hmm that is annoying :P I'm not sure I understand the last part of your comment. Could you explain it more? My apologies, I'm being slow today. – random Jul 23 '12 at 20:09