1

I have written a little PDF viewer which is supposed to show PDFs page by page to reduce memory usage. It consists of a PdfViewController which shows a specific page of the PDF (using UIScrollView, CATiledLayer).

Now the (maybe stupid) question is: if I want to show the next page (using a swipe gesture ot whatever), how would I do that? Should my controller handle it and update its views (which is a horror becaue CATiledLayer seems to crash as soon as you look at it :-)), or should there be an "outer" controller which generates a new PdfViewController for every page flip (the more flexible aproach)?

What is the best practice in these situations? Looking at UINavigationController, you're supposed to push a new UIViewController for every level. But there, all controllers being pushed may be different. In my case, all pages are using the same controller.

Krumelur
  • 32,180
  • 27
  • 124
  • 263

2 Answers2

1

You likely shouldn't use the UINavigationController for that. In general, the UINavController should be used for drill-down operations, where you have a limited set of items to be pushed.

In your case, I think the best option is to use a large UIScrollView which will take care of the pagination and then just create a new UIView with the CATiledlayer inside.

I created for my app Quicklytics a PagedViewController class that does most of that for you. You basically create a PageDataSource that creates the UIViews for each page, and handle it over to the control. You may not use this exactly as is on your code, but it'll give you a good idea on where to go:

https://github.com/escoz/monotouch-controls/blob/master/UICatalog/PagedViewController.cs

Hope this helps you.

Eduardo Scoz
  • 24,653
  • 6
  • 47
  • 62
  • You got that wrong. I don't use UINavigationController. I just used that as a comparison: UINavigationController IS a UIViewController and you push other UIViewControllers on it. So have you have boxed UIViewControllers. This is somehow against Apple's rule "one controller per screen". The thing is: it is logical and convienent. But if you box UIViewControllers, the inner controller ViewDidAppear etc. will not trigger. So I wonder if Apple is using kludges for all these controller-handlers like UINavigationController? Hence my question: do it the same way, or avoid it? – Krumelur Mar 12 '11 at 11:54
  • oh I was under the impression you wanted to use the UINavC itself for you app. The wouldn't call Apple's use of UIVC as a kludge.. Inner view controllers won't get triggered automatically because its unecessary.. Imagine the UINavC, would you prefer to fire the ViewDidAppear on all controllers in the stack all the time, or just the top one? So that kind of logic is inside the UINavC, and you would put in your custom controller as well.. take a look at that PagedViewController code to see what I mean. – Eduardo Scoz Mar 12 '11 at 16:24
0

Here are two useful resources Fast and Lean PDF Viewer for iPhone / iPad / iOs - tips and hints? collects a whole lot of information on displaying pdfs.

https://github.com/vfr/Reader a basic pdf reader for ios that does what you are trying to do.

In terms of whether to use nested UIViewControllers I would recommend against it, however if you do you should be aware that they will not handle rotation very well (I don't think they receive orientation change events) as well as viewDidAppear and other view lifecycle events, also make sure only to display modal view controllers from the root view controller otherwise they won't show properly (I had issues with them appearing in the wrong orientation in landscape, or in the wrong position).

In the app I built I used one UIViewController to manage the display of the pdf and I subclassed NSObject for any other "sub" controllers to make it more manageable. For example I had vertical scrolling as well as horizontal scrolling of pdf pages. My first attempt used nested UIViewControllers however I had issues with orientation till I rebuilt using controllers subclassed from NSObject for managing vertical slides.

Community
  • 1
  • 1
Daniel
  • 16