Are nib/xib files meant to be used in diffrent view controllers ? - ios

I watched multiple videos on youtube and bought two books with explanations (O'Reilly).
It seems like a nib file is always used in one view controller.
The file-owner is usually the view controller which will implement that nib.
I couldn't find an example in which a nib file is used in multiple view controllers.
I did come across a couple of posts that found ways around this but the posts are old and many people leave warnings.
My initial urge to use a nib file was because I had a table view cell that was used in multiple tableViewControllers. The tableViewCell was prototyped in one of the TableViewControllers in storyboard.
I thought that creating a nib would decouple that cell from one specific TableViewController.
I can't say that I really understand the purpose of a nib file.
It seems like it's very similar to storyboard.
I ended up creating the tableViewCell in code and reusing it throughout my project.
So my question is what are nib files used for ?
Are they used to decouple a view from a specific view controller ?
Are they used to avoid duplication within one ViewController ?
Any insight would be helpful.

Yes, you can reuse xibs in many places within your app.
Xibs predate storyboards and act as factories for creating instances of UIView classes configured in Interface Builder. Using them to define the layout and attributes of a UIViewController's view and its subviews is one common use case but certainly not the only one.
A common place where a xib might be reused is when it contains a table or collection view cell. You could then register that xib with multiple table or collection views using register(_ nib: UINib?,
forCellWithReuseIdentifier identifier: String) to load instances of the cell when needed.

Related

Using single storyboard views for static table view in iOS5+ instead of using storyboards for the entire app?

Recently I was searching for an useful approach for static table views without using storyboards for my entire app. I found this answer:
Static table view cells are only available when using storyboards. However, if you aren't using storyboards for your entire UI you can still use them for individual screens instead of a collection of strings.
To do this you can create a UIStoryboard file with a single view controller on it that has it's File's Owner set to your custom view controller subclass. Set the VC's identifier to some value. When you want to display this, get the storyboard and then instantiate your view controller subclass by creating the VC from your storyboard.
Is it a good approach? Or is it better to implement it the iOS4 way?
What should be preferred in case of performance and maintainable code base?
Thanks
Maintaining code base is pretty easy in Storyboard for static pages.

Different Segues from Different UITableViewCells?

This appears to be a storyboard editor issue because it's easy to do in code.
I have a UITableView with two different prototype cells. They have reuse identifiers, different accessories. I want selecting one type to trigger a segue to another view controller, and selecting the other to go to a different view controller. But as soon as I create the second segue in the storyboard editor, the first one is replaced. Even if I have named it.
It seems this should be a common enough scenario, I should be able to have multiple segues, and differentiate them in prepareForSegue.
I need to note, this is easy to do in the didSelectRowAtIndexPath for the view controller's table view delegate, but there I have to explicitly load the template from the storyboard (unless I use a generic and don't need a nib).
Has anyone been able to get this to work in the storyboard editor?
The only way I could think of to do this with how things currently work is by using two different types of prototype cells. (two separate classes) and assigning each different segue to each different subclassed prototype cell.

ViewController and Subclass ViewController with multiple Nibs

Is it possible to have a ViewController use one nib, while my ViewController's subclass points to another?
What I am trying to do:
I have an application that has a main menu that will take you to any section. Within the section you are in, you can pull down a different sub-section menu, which will take you to different pages.
I would like to have all the sub-section menu stuff be handled by a base ViewController class that each sub-section page would inherit from. That way I only need to write code to handle showing the sub-section menu in the base class, and all sub-section pages will automatically have it.
Though I don't know if it is possible to instantiate a ViewController with one nib, and tell it's base class to hookup to a different one.
Any help or tips appreciated :)
Thank you.
In iPhone-world, a UIViewController or UIViewController subclass is generally responsible for controlling an entire view hierarchy. This obviously breaks down in iPad-world with controllers such as the UISplitViewController.
So, I will make some assumptions about your app set up based on the description you gave above:
You might consider having a MainMenuViewController. This could, of course, inherit from some BaseViewController if you need it to, but the nib for the MainMenuViewController would allow you to navigate to the various sections. Perhaps this nib consists of nothing but a bunch of UIButtons. You tap a button and that takes you to a UIViewController subclass that corresponds to that section. For instance, if the section is Sports Teams, maybe that View Controller's nib consists of nothing but a UITableView that lists local sports teams. This View Controller can have a way to access this sub-section menu, which maybe lists details for a specific sports team. This "detail" section would be its own UIViewController subclass (inheriting from a base ViewController as you stated), which has its own nib, perhaps with UILabels listing the name, city, number of players, etc.
If the view hierarchy from one sub-menu to another is the same, you can reuse the view controller and just update the contents of its view hierarchy. If the view hierarchy is drastically different from sub-menu to sub-menu, you may want to consider a different UIViewController subclass that manages each sub-section's view hierarchy.

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/

Custom Sized Nib File Controllers and Interface Builder

I've recently been introduced to development for iOS by a friend and have begun to experiment with the interface builder and view controllers. One thing I'm finding is that when using a nib in conjunction with a view controller, your view controllers ivars are quickly polluted with views you may never actually reference. I would like to modularize the key components in my main nib into several different views. I have two questions regarding this:
How can I create a nib file for a custom sized view (one that doesn't fill the entire screen)?
How can I add the newly modularized to my main nib (all of the classes I would create for the components would be view controllers not views)?
Assuming I were to alloc and init the view controllers and add them to the main view programmatically, how could I position the custom sized views since I have already called initWithNibName:bundle:. I can't call initWithFrame: right?
Answers would be much appreciated!
Thanks,
PhpMyCoder
EDIT
I've discovered the answer to my first question. It seems that in the attributes inspector of your nib file you must disable the status bar (change it to unspecified) to enable the editing of the height and width parameters in the size inspector. However, I still am unsure of how to add these custom nibs and their view controllers to another nib without coding them in with initWithFrame: and addSubview:. Any ideas on adding a view controller's view to a nib in IB?
EDIT 2
Added question 3 (or 2 depending on how you think about it).
EDIT 3
I seem to be hastily asking questions today. A simple call to setFrame: will deal with sizing and positioning (and you can even append it on to your init function initWithNibName:bundle:frame:). Still not sure how to add the view (created by a nib) from a view controller to another nib in Interface Builder. If this is possible, I'd love to hear how.
Remember to not get ViewControllers and Views confused.
They are both in a hierarchy, and each ViewController has/controls a "main" view (which likely has bunches of subviews).
You don't add a view to a nib. A nib is a mechanism to help you assemble views. (A NeXT Interface Builder file, if we delve into nomenclature.)
This is how you load a nib:
[[NSBundle mainBundle] loadNibNamed:#"foo" owner:self options:nil];
Normally, you give a nib name to a controller and it does it for you, but you can do this to. There are complex and tricky ways to access the content. The following is the standard way to do it.
The owner you pass in must be the type declared as the owner in that nib file. It should have some of its outlets connected to objects in the nib file. After you load the nib file, they'll just "be there". If you called this twice, it would overwrite the first ones and replace them with the second ones. (mostly harmless, definitely useless)
So, typically, you wired it up to view. Now you have a view that's floating around in memory and not connected to the view hierarchy of the application. Time to do that. You must take view and figure out where it belongs in the pre-existing hierarchy and call [someOtherView addSubview:self.view] no it, and it will appear. Yes, if you want to explicitly place/size it, you will need to do that. Note that view.frame is in the superview's coordinate system.

Resources