When to use UIViewController Containment? (delegation overload) - ios

I have a view that contains a mapview and a tableview, similar to how to the facebook nearby places screen looks in the facebook app looks.
I put the screen together using interface builder. I have outlets to the tableview and map. And, I set the UIViewController that controls the main view to be the delegate for both the mapview and table view. Everything works perfectly.
However, this main UIViewController is now pretty messy because it has to respond to methods on behalf of it's own view, the mkmapview and the uitableview. However, data is somewhat shared between the map and the table view.
I am wondering if this is where UIViewController containment comes in? Or, if I should should just make custom objects to act as delegates for those two views. I am looking for the correct design pattern to use in modern iOS. A few years ago just mashing it all into the same controller would be the way to go. Maybe it still is the way to go.

Both your ideas are good thoughts, but...
Controller containment is typically used for more navigation related purposes, like a UINavigationController.
Custom objects that do some of the delegate/datasource work, that's a good thought too, but a little clumsy to the extent that they share data with the view controller and each other. This might be a good solution especially if other view controllers will need the same delegate/datasource behavior.
A third alternative, and probably the best of the three, is to create class extensions of the view controller (see apple doc here). These can be thought of as parts of your class in different files.

Related

Control vars/IBOutlets from one ViewController in another ViewController

I'm new to Swift, so I apologize for my lack of knowledge of almost anything related to Swift.
Right now, I'm developing an app that uses the ARSlidingPanel library, so now there are two ViewControllers present on the screen (Main view, with the dark background, and Panel view, which is the green background). I want to be able to set vars/call functions from the Panel view to the Main view. For example if I click a button in the panel view, I want to display some text in the main view. Right now I've started with using static vars but from my knowledge of Java/Android, I know this is probably not the right way to go. Any tips for a cleaner/more acceptable way of doing things?
There are a few different options here. However, the first thing that comes up to mind is if you really need to use two independent view controllers for the same view?.
One solution would be to use delegates. Write a swift protocol that has has the methods and functionality you want to expose, for example setting up values in the view controller's outlets, then implement the protocol in one view controller. In your other view controller, you can then create a delegate variable of type UIViewController -let delegate: UIViewController - and use that instance of your delegate to modify the view. Here's a guide on this
Even better, you can add view controllers as sub view controllers
of your view, apple provides a good bit of documentation on this, you
can find it
here.
Hope this helps.

UIViewController or UIView? Or even a better design solution?

I have a problem of designing an app. That's why I like to discuss it with you guys.
This app should be like a dashboard. You have several small windows/widgets that are filled with different data (images, tables, etc...) It is possible to add more widgets or remove them. Drag and drop aren't allowed.
What I am not sure about is designing it in the right way.
I will create one WidgetViewController for the widgets. So everything is kept encapsulated.
Then I will put all views in one "parent" UIViewController to use it with UIPagecontrol.
Is this a common way to have multiple UIVIewControllers in one UIViewController at all? I am not sure if this works anyway.
Or just create a class inherited from UIView?
You can have a container viewcontroller with uipagecontrol and uiscrollview that holds your widgets just like the weather app in ios.Depending on the different widgets you need to implement different viewcontrollers and add their views to scrollview.If you do not implement different view controller you might have difficulties handling your subviews since you need to control your views from a single view controller.

Using multiple nib files with a single view controller?

Background
I'm using interface builder to create the UI for an app I'm working on. The app has a single screen that displays a series of buttons. Clicking on a button displays an associated view which overlays the buttons. Clicking another button hides the previous overlay view and displays another one.
Too make managing the UI easier in IB I've decided to create multiple nib files for each sub view that is to appear when clicking the relevant button. I'm then loading the sub view's nib file in the view controller's viewDidLoad method using the UINib class.
The idea behind this was to avoid having multiple views stacked on top of each other in a single nib file as this would be hard to manipulate in IB. I could have created all the views in code but this would require a lot of tedious coding as the layouts of each sub view are quite complex (with multiple child views).
Example code loading a sub view from a nib file.
- (void)viewDidLoad
{
UINib *aSubViewNib = [UINib nibWithNibName:#"aSubView" bundle:nil];
NSArray *bundleObjects = [aSubViewNib instantiateWithOwner:self options:nil];
// get root view from bundle array
UIView *aSubView = [bundleObjects objectAtIndex:0];
[self.view addSubview:aSubView];
...
The code above is repeated for the other views.
To summarise I have a single screen iPhone app that has layered views that are shown/hidden by clicking buttons. This is achieved with a single view controller with an associated nib file and a series of additional nib files for the sub views which are loaded in the view controller's viewDidLoad method.
Questions!
Sorry for the long introduction but I wanted to be very clear what it is I am doing.
Is my approach bad or unusual?
Are there any potential issues to doing it this way?
What have other people done when they need a dynamic interface and
still want to keep everything in Interface Builder?
Notes
Before anyone asks why don't I just display the sub views on a new screen and use the navigation bar, let me say that I have very good reasons and I do understand iOS UI guidelines. The above use case is not exactly my use case but it's one that clearly describes the problem without getting bogged down in my development app.
Also I know I could have written all the sub views as code but each sub view has a complex layout of child views and it would be a lot of code and messing around to try and get them looking right.
Thanks in advance.
There isn't necessarily a 1-to-1 relationship between view controllers and views. Most views contain many subviews, which are views themselves, so this literally doesn't make sense.
However, depending on the complexity of the views (including their content), you may want separate view controllers... or not.
For example, if you have two sbuviews that are each tableViews, you may want to have one view controller for each tableView. This is because each tableView is looking at the same delegate methods, and if they are in the same viewController, then the delegate methods have to differentiate between the tableViews. The delegate methods have signatures that allow this, but, in my experience, it can really make for a messy code design that is hard to follow and hard to manage.
On the other hand, you may have two tables that are managed by the same viewController, where one table is filled with meaningful data and the other is simply a place holder (as when the data source is empty). One might be visible while the other is not. Why make you life complicated by creating two view controllers when both are driven by the same data source (the model)?
In my mind, it comes down to how difficult it is to follow and manage the code. If the complexity of using a single view controller becomes burdensome, consider using more view controllers.
UPDATE
By the way, I have an example that I am currently working with that may illustrate a similar situation. In the InAppSettingsKit, that a lot of developers use, there are several xib files for pieces of the main view. You can look at the structure here on github. There is one main view controllers and several xib files. (There is also what I would call a "helper" view controller and an email composer view controller.) In this example, the xib files may be used multiple times to specify the layout of table view cells. There is no view controller for each xib file, though. (The documentation for InAppSettingsKit is sparse, so these things may not be obvious just by taking a quick look at it.)
Every View should have a corresponding UIViewController. Using one ViewController to "Control" more than one view breaks the MVC paradigm. "Controlling" multiple "views" from one controller will make it much harder to change one thing without breaking something else. The choices you make on how to present the content to the end user will be different for every individual. So if you say a NavigationController won't work in your case, maybe a Modal view is the answer or, you might just instantiate your custom UIViewControllers and add them to your view ([addSubview:]), if thats the road you want, but like I said, it would be beneficial for you to make a "controller" for each view object along with the corresponding xib. If you need information sent back, use a delegate or use Notifications to send the message back to the parent view. I learned the hard way that not following MVC paradigm, will make you life miserable. Try and keep your code as decoupled as possible. And read up on the MVC design pattern, you won't regret it.
actually its possible to do this.
Open your .xib file,select File’s Owner(in placeholder) -> "identity inspector" (utilities) -> change class name to your controller classname -> press control and drag file's owner placeholder to View object, select "view" in dialog.
Now you can customize your view.
p.s. you can use the same outlets as first xib, you need only to drag them to the new xib(+control sure).
here is an explained tutorial:
http://irawd.wordpress.com/2013/09/05/how-to-link-a-xib-file-to-a-class-and-use-2-xib-files-for-iphone4-and-iphone5/

To subclass or not to subclass : that is the ...?

I am building an app with many views and subviews.
I am trying to figure out how to approach creation of the subclass.
one simple example:
I have a table view with heads view and footer view. (I have much more complex views then this one, but I am trying to explain my point with a simple one).
In the beginning I didn't want to create views subclasses for every view, but I found that my code is getting complex and hard to navigate in.
Then I found my self creating a view for every subview in the main view. The truth is that I like it better cause my code is clearer to me. Th only thing is that I don't know what are to cons and pros of each approach.
How do you decide when to create a custom view or create it's code in the main view?
Thanks
I usually create a UIView subclass only when there is specific functionality that would be best done in such a class. This might be that the view is a control such as a keyboard to enter a value or a UITableViewCell subclass.
Otherwise I would generally not subclass UIView but just create the view hierarchy in Interface Builder or in code and then use the UIViewController subclass to do all the business logic.
Basically, in general with iOS programming, you want to have all the logic of how a "view" (or screen, or whatever you want to call it) in a UIViewController subclass. It's hard though to really give good advice without fully understanding your hierarchy.

UIViewControllers in UIScrollView?

I have a design question. I have a scroll view that I want to use as a means of navigation. I.e. the user can slide between screens. At present, I am creating view controllers and putting their views directly on the scroll view:
aViewController.view.frame=CGRectMake(0,0,320,200);
[self.myScrollView addSubview:[aViewController view]]
Etc, for all 3 view controllers.
I know this isn't best practice. But I can't think of any other way of doing it. Ideally I would like to get the same behaviour as a navigation controller except the fact that I'll be using a scroll view. Any help would be greatly appreciated.
You have to be aware that this breaks certain UIViewController behaviors because these child view controllers do not get informed about interface rotation events and their viewWill/Did(Dis)Appear: methods will not work.
The alternative (until iOS 4.x at least) is to not use UIViewController subclasses for these subviews. You could easily create your own custom controller class (derived from NSObject) to manage a child view.
It's debatable whether that approach makes it easier overall, though.
I'm guessing what you're trying to achieve is something similar to this app?
http://itunes.apple.com/us/app/fanhattan-for-ipad/id436928538?mt=8
This app works in the same manner, using a scroll view for navigation. You can analyze that app, you'd get some ideas from it, i'm sure.

Resources