iOS - Different ViewControllers - how to load them? - ios

I’m trying to develop an app that uses 3 different view controllers on the first tab. I have 3 options:
1 - embed the view controllers in an uipageviewcontroller
2 - embed the view controllers in a uiscrollview
3 - use containers controlled by a uisegmentedcontroller - with hidden property true or false…
Each of these viewcontrollers are using collectionviews to present photos downloaded asynch from a remote server.
Using 3, the photos from all view controllers, loads at the same time, so, this isn’t a good solution I think.
Which one is the best solution to choose in this scenario?

If you're worried about downloading large images simultaneously then only begin the download process in viewDidAppear. Unless the user opens one of your view controllers the download process will not kick in.
If you're worried about multiple view controllers sitting in memory then you should design them well. Using a UITableViewController or a UICollectionView will help you keep your memory usage low by reusing views.
In my opinion you should pick a solution according to your UI design and simply build your code efficiently so you won't have to worry about large downloads or running out of memory

You didn't mention a tab bar controller, which is another viable option. (Or maybe that's what you meant instead of UISegmentedControl?)
Which is best depends on the UX you want for your app more than anything.
I would put the segmented control at the bottom of the list. It's a non-standard UI, and will also require a lot of custom work from you.

Related

Best way to switch between multiple view controllers while preserving any downloaded data?

What is the best way to have multiple UIViewControllers that can be accessed from a side menu and without having to re-download any data each time the view controller is shown?
Say for example I have three view controllers, one is a homepage that shows recent notifications, one is a news page that shows recent articles and one is a page that has a collection of images. When each view controller is loaded, data is downloaded from a remote server and displayed - if the user switches to another view controller and back again I want the previously downloaded data to be shown immediately without having to be re-downloaded (until a UIRefreshControl is used or similar).
Off the top of my head I can see this being achieved in 4 ways:
Store the data in a singleton and load the data from this if it has been previously downloaded, however, this seems to go against general practices that I have seen and also doesn't seem efficient - especially if there is a lot of data and/or multiple view controller.
Use a UITabBarController that selects the index based on the side menu instead of the traditional bottom bar, would this cause issues if there were 10-12 items on the side menu?
Cache the data to disk (using NSCache etc) and instantiate/dismiss each view controller as needed, the view controller can use the cached data - only one view controller will exist in memory at a time.
Use some kind of customised container view that caches the view controllers and loads them as they are needed, feels a bit hacky and not very efficient?
What are the best ways to achieve this? Most tutorials I see just show how to segue/present view controllers but I have struggled to find anything that explains how to preserve the data that was downloaded on them.
Just as an FYI. If one of your ViewControllers is supposed to "show recent notifications/articles" then caching data won't work because it might not be the most recent unless you pull from the server every time. (Unless the recents are getting pushed and even then you might have huge sync issues if you don't pull every time.)
That said, you options 1 and 3 are effectively the same, the only difference is where you are keeping the information.
You should not be using a tab bar controller. If you can't use UISplitViewController then you should make your own custom container view controller.
As for the caching issue. I would implement some sort of caching mechanism for each endpoint. It could store in ram or on disk but I think in ram is better because the data sounds pretty volatile.
Set it up so that when a view controller makes a "network" call, the function it uses calls the closure with the last data it pulled and then optionally can make the network call again and call the closure a second time with the new data. This way the VCs will be very responsive in getting data up ASAP and still pull in the new data on every view will appear.
I would go with a combination of option 3 and 4.
There are many formats you could use to cache the data to disk. You could use a database like CoreData or Realm, or write directly to files as a Plist, JSON, NSKeyedArchive.
You probably should build a container view controller as well. Thats what a TabBarController is after all. It's pretty easy to do and the docs cover what you need to do. This will make you app more efficient by only having to load data from the database/file the first tome you go to the view controller. Then when switching sections, it can just show the VC thats already been loaded.

Should optional views be added by storyboard/xib and then hidden or added programmatically? (Good practices)

I'm starting a new project and I have some doubts about storyboard good practices, specifically about optional hidden views (show only under certain circumstances).
Let's say you have an pdf downloader app, when the user select a download button a UIProgress bar appears and show the download progress. Should this progress bar be included in the storyboard or generated programmatically when the user press the download button?
It's a simple example but what about if there isn't only a UIProgressBar but also multiple hidden (optional) buttons? What if some of the buttons are overlapped? (I know overlapped button is bad design but just for the purpose of exemplify)
Should this ones be hidden or added programmatically? What about performance? Some say it takes more time to parse a Storyboard/Xib than a programmatically build view.
In DonaldKnuth's paper "Structured Programming With GoTo Statements", he wrote: "Programmers waste enormous amounts of time thinking about, or worrying about, the speed of noncritical parts of their programs, and these attempts at efficiency actually have a strong negative impact when debugging and maintenance are considered. We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil. Yet we should not pass up our opportunities in that critical 3%."
So, you are trying to solve a performance problem you do not really have (at the moment).
You decision to have a view permanently or temporarily should be based on context of the view usage, not some hearsay performance issues between xib/stb vs programmatic approach, that resembles platform-wars, but otherwise, given how LLVM compiler works today, and what the HW performance of iPhone 4 or higher is, is basically nonsense.
Here's a simple rule. Have all the views in IB, hide or unhide them as necessary, and add/remove a view programatically only if you can give a good reason why.
I understand you instinctive desire to make it right, so instead of trying to manage one milion views in one controller, take a look at the problem that is satirically called Massive View Controller.
Proper decomposition into custom views, separation of concerns, clearly defined responsibilities split into more view controllers, view controller containment, is the answer to to address your concerns.
You want your app first and foremost to work correctly.That you can achieve by having a sound architecture so that you will be able to stay in control. Users will not appreciate that you instantiated some button programatically, because they couldn't care less. But if the app has inconsistent state because your view controller has 7000 lines and is spaghetti hell or is crashing, that is a problem.
if you are planning to use storyboards; would suggest to have view/buttons etc included . you can always hide / unhide the same from the code.
have a thought process and not cluster your view. Have multiple views and make your app look neat

Which is best if I wanted Page based design?

Which one is good to use for a page based design, Pageviewcontroller or UIScrollview with paging.
Which will consume less memory? I have done it via UIScrollview; but it's consuming very huge memory. Any help will be greatly appreciated.
Using UIScrollView for the application is not a handy task. For iOS 6, you should use UIPageViewController. But for iOS 5, UIPageViewController is not be good as it only provides scrolling for the page transition.
You may reuse the UIScrollView views then,
Many examples are there in SO like this
It is hard to say which is "best" - it depends on what makes sense for your app. Which ever approach you choose you can minimise memory consumption by "lazy loading" content into the scroll view when it is needed. For example, if you were displaying pages of images and the images are stored as files in your app then you should only add the current image and the image either side of the current image. As you scroll you can load and add the next image and release.
Here is a tutorial that shows this approach with UIScrollView- Multiple virtual pages in a UIScrollView with just 2 child views
UIPageViewController makes it a bit simpler by adopting a dataSource pattern, so you can concentrate on responding to data requests and not have to worry about manipulating the views.

How many view controllers is too many view controllers?

I'm creating a reference app for a game showing everything the user needs to know in order to be good at the game. Weapons, maps, random information, etc.
I am 1/10 of the way done and I already have over 45 views controllers in my storyboard. I only have one storyboard since I don't know how to create another one and link it to the first storyboard. The storyboard is starting to lag a little bit. How many views is too many views?
Once I'm done, I'm guessing I'll have over 100 view controllers in one storyboard. Is that too many? If yes, is there a simple way to fix that problem?
(I have so many views controllers because I created one for every individual item.)
I would create 5 storyboards (one for every category in the main menu) to see if it would reduce the lag, but I don't want to do that if it's not going to help.
You can create multiple storyboards in one application and Apple do not stops you from doing that. It is highly recommend to divide your app screens into modules and put those modules into different storyboards and navigate between them flawlessly.
You can have a look at this library for integrating multiple stroyboards in your application:
https://github.com/rob-brown/RBStoryboardLink

Composing user interfaces without nesting viewcontrollers

I am pretty new to IOS but have completed a couple of simple apps.
I have read a number of books, which have helped me getting started, but I am missing som more generel advice on how to best structure an app - especially with regards to UI.
I know this is a very general question, so I will try to put up a specific problem. Suggestions on how to structure this particular app .. or pointers on good reads regarding similar topics would be highly appreciated.
Now the UI of this particular iPad App will look as follows:
The main screen is divided horisontally in two.
Upper two thirds is a sort of canvas / work space
Lower third is a toolbox with various items, which can be dragged to the work space.
The toolbox has different views which holds items in various categories. Lets say: One view with various geometric figures and one wiew with various colors. The user can choose which category to show in the toolbox.
Finally at the top of the screen is a toolbar with a single button.
I am a bit confused as to how to structure my views / ViewControllers. Maybe a lot of my trouble stems from me not fully understanding Apples guideline as to how to use various UI Elements - please feel free to say so if this is the case.
This is how I would start out.
I would construct a main ViewController controlling a main view. The main view would hold the upper toolbar. To this view I would add two subviews. One for the work space and one for the toolbox. The toolbox view confuses me a bit. My idea is making this a tabbed view with one tab for each category of items. However as I understand it, it is bound to cause lots of trouble nesting viewcontrollers which would be the case. Does this imply that using a tabviewcontroller to control only part of the screen is against guidelines? Would it be much better to make up my own 'tabbar' and simply switch between subviews when a tab is tabbed?
Does this also imply, that having a popup view, covering only part of the screen, with a navigationcontroller is equally bad practice? Or would this have to be a modal view? And how about a tableviewcontroller with a view taking up only part of the screen? I fail to see how to accomplish these things without effectively nesting viewcontrollers.
I am sure I got something completely upside down?
Best regards
Thomas
Nesting ViewControllers is not a problem. In fact, View Controller Containment was introduced in iOS 5 to make this even easier. However, it was still possible before the new containment functions.
The easiest way to nest two ViewControllers is the following:
SubViewController *theSubView = [[SubViewController alloc] init];
[self.view addSubview:theSubView.view];
The subview will then be controlled by the SubViewController and will be "nested" in the main ViewController. (This code would be part of the main ViewController.)
To use the new(er) View Controller Containment methods you will make the SubViewController a childViewController of the main ViewController.
There is an excellent video from WWDC 2011 that goes over View Controller Containment. You will need to be a developer to access it here. It is called "Implementing UIViewController Containment."
I would not advise to use the TabBarController in a nested format, it would be easier for you to just build your own view switching method or even use a UIScrollView with pagingEnabled.
As far as popup views with NavigationControllers, this is a common practice. There is nothing wrong with creating a popup with a NavigationController inside of it for doing something like, accessing app settings, or configuring a tool from you palette, or accessing saved projects, whatever you can imagine.
I hope this gets you off to a good start.

Resources