Is it possible to embed only part of a view controller inside a container view? - ios

I want to create a view controller that will reuse parts of other controllers from my app. Ideally, the new controller will have 3 containers, with one container for the header (c1) and two other containers bellow it (c2 and c3).
So for c1, I am trying to embed only the view from the controller that holds the header, but doing it in storyboard only allows me to embed the entire view controller where the header is. When I try to drag from the container into the header, the whole view controller is highlighted and I cannot select the header alone. I have also tried just copying the header, but it's A LOT of repeated code.
I will also face the same challenge when trying to embed an existing table view in c2. So is it possible to embed just part of a controller inside a container view? I don't have to stick to the storyboard, so if someone could share how they solved this programatically that would also help a lot.

What you want to do is put your reusable views in a .xib file. That is the way to make perfect copies of complex hierarchies of views. Every time the .xib file is loaded you get a fresh copy of the whole view and its subviews as you've designed it in Interface Builder. The loading must be done in code but there are ways to make a superview that does that automatically.
This screenshot demonstrates:
There is no duplication going on here, just three independent copies of the same .xib file, created automatically. They are all in one screen but that's just to make it easy to make the screenshot; these elements could be anywhere in the app's interface.

Related

Same TableView in multiple locations swift 3

In my current app I have a tableview that I would like to display on multiple view controllers, I know I could copy and paste the code from one view controller to another but I know enough about coding techniques that copying and pasting large sections of code is bad practice but not enough to know a way to avoid it in this current situation. I am using swift 3 and a standard table view. Does anybody have any good suggestions for me?
If you're using interface builder, you can create a view controller with only your tableview in it and "embed" it in other view controllers using a container view.
IB will create a new embedded view controller when you add the container view but you can delete that and relink the container view to the one containing you tabelview.

Is there a way to make one view a subview of another in Interface Builder without actually dragging it inside the other view?

In this xib, I have three views: the main view and two container views which go inside it. Since you can't hide/show views in IB, it isn't practical to actually have the container views inside the main view since they just obscure each other. By moving them outside the main view like this, I can design them easily, but I must add them to the main view inside the controller's viewDidLoad. Is there a way I could have done this in IB?
Note: I know you can push a new controller for this specific kind of control, but I don't feel like coming up with another example just to ask the question.

How to see a particular view clearly amongst lots of overlapping UIViews

When a view controller (VC) has hordes of views and subviews it becomes very difficult to modify a subview because I can't even see it completely (it is hidden behind some other subview). For example please have a look at current state of one of my VC:
I can't see highlighted "Congratulations - UILabel" or its UIView.
Is there a way I can see a specific view clearly (may be at the top of all the other views)?
Generally I drag drop a UIView on a different dummy blank VC, design view completely on that VC with all constraints and finally drag drop it back to my actual VC. This works most of the times but it seems like an inefficient approach to me.
I've observed that seeing overlapping views used to be easier in iOS6 but it is Very difficult in iOS7. Is there any feature in iOS7 Interface Builder that I am missing? Thanks for your precious time.
Update: Would Spark Inspector help me here? I am newbie to development so don't want to waste my time trying and understanding new plugin if it doesn't help me achieve what I want. Thanks.
This is widely considered one of the weak points of Xcode's new Storyboards feature. They're great for apps that require a large number of simple controllers, but they become difficult to work with when your interfaces get complicated. Most experienced developers use Storyboards in some places and individual controller XIBs in others, depending on what they're building.
Here's how to solve your problem:
Step 1. Break the View Controller out of your Storyboard into it's own XIB
From the File menu, choose New File and choose an Empty XIB file (from the User Interface section). Name it "YourExactVCClassName.xib".
Go to your Storyboard. Copy the entire View of your View Controller and then delete it.
Paste the View Controller into your new XIB. Change the class of "File's Owner" to be your View Controller, and set it's "view" property by drawing an outlet from the view to File's Owner.
When your app runs, it will try to instantiate the view controller
from your storyboard. When it realizes there's no view in the
storyboard for that controller, it will automatically find the file
MyViewController.xib and load it from there.
Step 2. Organize the contents of your main view into detached views that make sense.
In your example above, it looks like you have different views for different states of the game (game over, high score, etc.) Take each of those and remove them from the main view. With your controller in it's own XIB file, you can just drag the view out in to the whitespace around your controller. Each view you drag out becomes a top level object in the XIB file that you can design and see easily.
You're no longer stuck with an iPhone-5-sized workspace.
Create IBOutlets for each of your detached, top level views so you can reference them in your controller.
In viewDidLoad, programmatically add each of the separate views to your main view. Note that you may want to set their frames, make some of them invisible, etc. You have to write more code, but it's generally worth it for an easily maintainable XIB.

Do I need a View or a ViewController?

I'm building a custom view with an xib file that contains various subcontrols. I've got some container control that needs to hold my custom view. I'm kind of unclear on whether I need to make a View that somehow loads itself from the xib file, or a ViewController that does this.
However it's done, I'd like my custom view to be reusable, and something that appears in the toolbox in Xcode, along side buttons and textboxes and such, so I can visually design other views containing my custom view.
What is the right way to do this?
Does your component manages other view controllers (like UITabBarViewController does for example)? If yes, make it a subclass of view controller, if not, and it's just a control, like a switch or a fancy button, scroll wheel etc, then make it a subclass of UIView.

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/

Resources