MainWindow .xib - iPhone Development - iphone

It is my understanding that every view has it's own controller class. I know generally that the xib file is the application view/subview. My question is does the MainWindow.xib have it's own controller and if so, where can it be found?

You are right in that a xib file can allow to associate a view to its view controller.
Now, MainWindow.xib contains the main UIWindow for your app (at least). UIWindow is not a UIView and does not need a UIViewController.
On the other hand, you can create any object you like inside of a MainWindow.xib, so you can also have a UIView in there, which you then add to the UIWindow instance, and its corresponding UIViewController.
If you think about additional xibs, what happens with them is that they define a UIView, and additionally also specify the File's Owner type, which is usually UIViewController and gets instantiated by loading the xib.
In this sense, MainWindow.xib, though not requiring a UIViewController, still needs a File's Owner, and this is the UIApplication singleton. Since you cannot modify nor derive a class from UIApplication, the way to interact with the UIWindow instance is through the UIApplication's delegate.
Take in mind that MainWindow.xib plays a special role, in that it is also specified in the info.plist file. You can do without one (by removing the corresponding entry from info.plist) and simply declare your application delegate when calling UIApplicationMain from main.c. In this case, nor application delegate neither the UIWindow will be instantiated through the xib mechanism; you will need to instantiate a UIWindow from you application delegate's applicationDidFinishLaunching.

I don't think it has its own controller. It is the main window basically the thing that pops up when application comes up. We add controllers or view controllers for the user to use. App delegate is sort of the controller but not exactly. we override applicationDidFinishLaunchingWithOptions to any controllers etc so appdelegate can be thought of as the controller of the mainwindow.xib although it isnt.

Related

Where can I change the window my app uses from UIWindow to my own subclass "MyWindow" with storyboard?

I've got a universal project here with storyboard. I've created a subclass of UIWindow called MyWindow, and I need to load it instead of the default UIWindow. Prior to storyboard, I would simply go to the .XIB file in XCode and change the class for the main window to MyWindow. However, I'm unable to find any section where I can change this in storyboard.
Does anyone know where I can do this? I need the main window to load MyWindow, not UIWindow.
When using storyboards the application delegate and main window are no longer represented in Interface Builder. Instead, when your app starts, your app delegate is queried for a property called 'window'. If this returns nil then a default window of type UIWindow is created for you. To change this behaviour you need to implement a 'window' getter method in your app delegate that returns your 'MyWindow' subclass. See the documentation.

How would I change the default loaded view controller in Xcode?

How would I do this? Is it simple enough to explain clearly? If not, a tutorial would be nice. I checked the web and this site and still couldn't find exactly what I was looking for.
The default XIB file loaded when your application start is MainWindow.xib by default.
If you want you app to load another XIB instead, this can be changed in the Info.plist file of your project.
In this XIB loaded when the app is launched (MainWindow.XIB by default), you will find:
a placeholder for the File's Owner (like in any XIB) which in the case of the XIB loaded by the application on startup is the UIApplication itself.
a UIWindow (the main and unique window of your iPhone app),
an object that acts as the delegate of your UIApplication (commonly called "the AppDelegate")
And probably a UIViewController too.
When the XIB is loaded at startup, the AppDelegate objet is instanciated (like all objects in the XIB except the File's Owner) and as it is set as the delegate of the application, application:didFinishLaunhcingWithOptions: will be executed. This code then generally add the viewController's view as a subview of your app window using a line like [self.window addSubview:self.viewController.view]. (As your AppDelegate have an IBOutlet that points to the ViewController in the XIB)
If you need to change the class of the ViewController used in your MainWindow.xib, change the class of the UIViewController in Interface Builder, and also change the type of the associated IBOutlet in the AppDelegate header file.

How to provide an own UIWindow subclass as the main window in an iPhone app?

For inspecting all events posted to the views of the window, I want to make a subclass of UIWindow and make that -keyAndVisible in the app delegate.
However, my project already came with an nasty MainWindow.xib file ;-) so I find it hard to do that now, since that nib guy is creating the window. Is there any way I can get rid of this MainWindow.xib? Or is there another way to have an subclass of UIWindow in place?
Or in Interface Builder you can change the Window's class from UIWindow to your subclass in MainWindow.xib (using the Identity Inspector).
Just delete MainWindow.xib remove refrences from info.plist and your app delegate. Then you can create an instance of your custom window in the app delegate and call keyAndVisible like the app delegate currently does.

What are the conventions for declaring a UITabBarController in mainwindow.xib?

I have a mainwindow.xib file with a UITabBarController as the base view controller of the app. So inside the UITabBarController I've added about 10 sub UIViewController objects as tabs. Most of them are just a UITableViewController subclass or a UINavigationController containing a UITableViewController subclass.
In this design, each UIViewController is fully loaded on app startup, including calling the viewDidLoad method of each view controller. Is there any way to get around that? Since the view controllers are just UITableViewControllers with no other outlets, it seems excessive to create a NIB for each tab (which I assume would allow the viewDidLoad to only get called when the user first switches to the tab? Or am I wrong on that?)
Anyway, my question mainly, is: how is it conventionally done? If you have 10 different view controllers on one UITabBarController, do you put them all in mainwindow.xib? If so, should each have its own NIB, and if not, where do you put them, and how do you add them to the tab bar?
What you want to do is to define the UIViewController views in a different xib file for each view - the reason they all get instantiated is that when the xib loads, all objects held in the xib load - and that means all your views and view controllers since you have defined them there.
In MainWindow.xib where you have the tab bar defined, you can still set within each tab the view controller type that will be called and also the XIB file to use for that type (create a new project with the "TabBar application" template and the second default view will be like this).
Then as you press tabs the view controllers will be instantiated from the different XIB files you have defined.
Note that this means if you are using IB to add buttons to the navigation bar, you have to do that back in the TabBar xib and not in the xib you use to define the view. You can still link actions to the view controller definition within the tab.
The way Apple suggests doing it for pure NIB files is how you say: Each sub-view in its own NIB file.
Instead of doing this, I would create the UITabBarController programmatically. That way you can define all your simple views in code, and still load complex views from NIB files.
Personally, I prefer creating as many of my views programatically as possible. The compiled code has a smaller footprint than the NIB files and I feel like I have more control. I mostly use Interface Builder to mock up applications.

How to keep controllers out of xib

As a newbie, IB and all the possible connections is bewildering to me. Most tutorials I've found are what I'd call the reincarnation of spaghetti code, in which the entanglement is all the connections created by dragging. Of course, I want to use IB for layout of views (sizing & placing visual elements), that's what IB is great for. But a controller is not a view, so it's less confusing if all my controllers are solely code and don't appear anywhere in IB. I suspect this will minimize the spaghetti. It also encourages the one-xib-per-view admonishment. To that end, and here's the question, where can I find example projects that adhere to this strategy?
I don't have a set of sample projects, but I will give you some information about how things work and when you should create controller's in a XIB file or in code.
If your controllers are created dynamically by way of a user's action, you typically won't instantiate them in a XIB file. Instead, you'll instantiate them in code like harms mentions above. Once you do that, you'll still need a mechanism to connect this controller that was created in code, to the user interface elements that you've created in IB.
The mechanism that IB provides for solving this is the File's Owner. Mastering the File's Owner is essential to "getting" Interface Builder.
The file's owner is not an object that is "in" the XIB file, it's an object that's represented in the XIB file. It's a placeholder for an object that will already exist when the XIB file is loaded. When NIB files are loaded at run time, they're loaded with the NSBundle method -[NSBundle loadNibNamed:ownwer:options:]. The owner parameter is used to resolve the file's owner placeholder object in the XIB/NIB file. When the file is loaded at runtime, all of the connections made against the file's owner will resolve against the object you passed in as the owner parameter to the NSBundle method. On the iPhone, you typically don't load NIB file yourself. Instead UIViewController does it for you. The default implementation of UIViewController's loadView method might look something like this:
- (void)loadView {
[[self nibBundle] loadNibNamed:[self nibName] owner:self options:nil];
}
So, by connecting the elements in your XIB file to the file's owner, you'll be connecting them to your view controller.
You will have some controllers that are statically in your application - they'll be alive forever. A navigation or tab controller along with their root items are typically alive for for the entire life of their application. When that's the case, I'd set those view controllers up in the MainWindow.xib file. Most of the other controllers would be created dynamically, and programatically in response the the user doing things.
Good question. The pattern I try to stick with is making the controller in code, adding IBOutlets and IBActions for the things in the XIB/NIB that interact with that code, and a thing in the controller's constructor which loads the XIB/NIB with "self" as the owner, and in IB I connect stuff to the "File's Owner" placeholder, whose identity I will have specified to be the my controller's class.