I'm just starting iPhone development (coming fron a .Net world) and have been going through many "Hello World" applications to get the hang of this new development platform. One area I have been confused with is the instantiation of a view controller. On an Apple "Hello World" tutorial, they start by creating a Window Based App, which by default has no view controller. They then create a UIViewController and manually instantiate that controller in the application delegate, followed by simply adding the view controller to the window (http://developer.apple.com/iphone/library/documentation/iPhone/Conceptual/iPhone101/Articles/03_AddingViewController.html#//apple_ref/doc/uid/TP40007514-CH5-SW5).
In contrast, if I were to create a new "View based application" project and look at the delegate implementation, all that was done to link that view controller to the main window was the following line:
[window addSubview:viewController.view];
Why does the tutorial indicate I must manually instantiate the view controller via alloc/init, when the pre-built "view based application" template simply adds the view controllers view to the window? What's the difference between the two?
From doing some more digging, I found out the answer to my own question. When you create a View Based Application, you'll notice that if you double-click the MainWindow.xib, one of the objects in the Document Window is a View Controller which is already connected to the [ProjectName]ViewController class (a class which was automatically created when you selected the View Based Application).
Hence, by dragging in a View Controller from the Library to the Document Window in MainWindow.xib, you are in essence INSTANTIATING that object (although it's archived in the nib file). Therefore, there is no need to instantiate it manually in the application delegate. Simply add that view controllers' view to the window and you're done.
Related
I am creating a project that requires changing views. However, no matter what segue I choose, the new view opens in a new window when I press the button to open the new view. Is there any way to have the new view replace the old one in the same window, either programmatically or within the Storyboard?
Yes, the term you want to search for is view controller containment.
Here's the basic idea: Apple ships its own "container" view controllers like UINavigationController and UITabController, which manage view controllers for you (i.e. how they are presented, how you transition from one to the next). If those don't work for you, you can build your own (which can themselves be used within those built-in containers btw). Here's some documentation:
https://www.hackingwithswift.com/example-code/uikit/how-to-use-view-controller-containment
https://developer.apple.com/library/archive/featuredarticles/ViewControllerPGforiPhoneOS/ImplementingaContainerViewController.html
In a navigation based application, when I want to create and use other uiviews and uitableviews I need to create their controller and views. in an example I saw that I can simply create a new controller with .xib file, design it, and just call that xib file from my navigationcontroller.
In another example, some stuff was going on also in the mainwindow.xib and some new controllers and navigation items were added from the mainwindow.xib.
What is the difference between these methods? when and why I should need to open and edit the mainwindow.xib file to add a controller?
The mainwindow.xib is your UIWindow component which you can see as a representation of your iphone screen, it will always be there no matter what. In your examples when you are showing your view controller dirrctly that is because the controller is already a subview of your UIWindow which is the mainwindow.xib in the Interface Builder.
There really is no difference between the 2 methods, in the first one you are adding your controller as a subview progrmatically using:
[window addsubview:mynavcontroller]
And in the second one youbare doing it thru interface builder, you may use whichever method you feel more comfortable with.
You do not really need a controller to show a view, however they can be handy if you want to do any extra stuff such as rotating your view or loading certain data when the view is loading. That being said you could add your view as a subview of your window and it would still work.
What I am trying to learn is what is the difference between the window, and viewcontroller. I know that you can only have one window per application. But you can have multiple viewcontrollers. When I create a project thats based off of the window-based application template I get only a window. I can create my own viewcontrollers, but I also know that I can put things directly onto the window in a window-based application (I think correct me if I am wrong). But with a view-based application I of course get a view that I can add things to. Can anyone clarify any of this for me if I make any sense?
Basically you have one instance of UIWindow that's hosting all your UIViewControllers and UIViews as part of the view hierarchy. That's why UIApplication has a call [UIApplication sharedApplication].keyWindow, to access the "root" view.
So for example you can have the following stack:
[UIApplication sharedApplication].keyWindow ->
MyView ->
MyOtherViewController
For more information, read up the Developer Documentation on UIWindow and UIViewController which provide a great explanation on the differences.
They're two completely different things. A window is a view that's special mainly in that it doesn't have a superview; it's the container that holds all other views. Because of its position at the root of the view containment tree, a window helps in the process of dispatching events to the proper views and redrawing as needed. Other than that, the window doesn't worry too much about the views it contains.
A view controller is not a view at all. It's a controller that manages a view and all its subviews. A view controller typically responds to user input from controls, populates views with the data they need, manages visibility of subviews, etc. The view that a view controller manages is installed in a window when that view controller is active, but the view controller generally doesn't keep a direct reference to the window itself.
I have an application, say 'MyApp', which by default loads the view controller 'MyAppViewController' whenever the application launches. Later, I added a new view controller 'NewViewControler' to the project.
I now want the 'NewViewController' to be my default view controller which loads when the app launches.
Please let me know what changes I need to make in my project to achieve this.
Its easy, just:
Open your Storyboard
Click on the View Controller corresponding to the view that you want to be the initial view
Open the Attributes Inspector
Select the "Is Initial View Controller" check box in the View Controller section
Open MainWindow.xib and replace MyAppViewController with NewViewController.
In your app delegate class, replace the property for MyAppViewController with one for NewViewController. Connect NewViewController to its new outlet in Interface Builder.
In application:didFinishLaunchingWithOptions: add NewViewController's view to the window instead of MyAppViewController's view.
Most likely your main NIB file is still set to "MainWindow", check your *-Info.plist file.
If that's the case you can open the MainWindow.xib in Interface Builder. You should see a View Controller item. Bring up the inspector window and change the Class Identity to point to your new class. That should take care of instantiating your class.
As this feels like a "newbie" question (please pardon me if I'm mistaken) I would also highly recommend the following article:
iPhone Programming Fundamentals: Understanding View Controllers
Helped me understand the whole ViewController thing and the IB interaction..
As for me with xcode 4.3.3, all I had to do was simply replace all references of 'MyAppViewController' with 'NewViewController' in the AppDelegate h and m files.
Perhaps all the other steps have been taken out in the newer versions of xcode.
Hope this helps.
In Interface Builder... when I drag a VIEW into the document window... and then double-click on it... it opens and displays the VIEW window. (As expected)
... but when I drag a VIEW CONTROLLER into the document window... and then double-click on it... it also opens and displays the VIEW window, too. (It says "view" right on it.)
Is that right? (Or am I totally misunderstanding things?)
I thought a VIEW was the actual object to draw/drag things into. No?
I thought a VIEW CONTROLLER was just the CODE for your view. No?
I dont have experience with Interface Builder, but a a controller object provides the custom logic needed to bridge the application’s data to the views. In iPhone applications, a view controller is a specific type of controller object that you use to present and manage the views of your application.
Each ViewController has a View property associated to it, which is the one you are seeing in interface builder.
The view stored in this property represents the root view for the view controller’s view hierarchy. Whenever you present the view controller on screen (either modally or as part of view controller–based interface), this view is retrieved and displayed in the application window. The default value of this property is nil
Each view controller object is the sole owner of its view. You must not associate the same view object with multiple view controller objects.
Apple wants you to follow the Model-View-Controller system when you develop apps, and it's pretty straightforward and logical.
The Model is the core of your app. It processes databases, network connections and whatever you need. It's basically custom classes you create in Xcode.
The View is the interface between your app and your users. You can create them in Interface Builder and put them in NIB files (preferably one view every file).
The Controller is the glue between your view and your model. It defines the behavior and state of views (button enabled, label content, etc.) based on what it gets from the model (like a database). It also performs actions on the model based on the events it receives from the views it managers (controls), like changing records in a database or changing variables in objects.
The idea behind all this is that the model can be used in every platform with minimal modification.
Every controller should be linked to one view, and one view only, like a table (UITableViewController) or a screen's view (UIViewController). You subclass the controller you want and you add it to the NIB of the view it's associated with. That's how you do it:
In the NIB, select the File's Owner.
In the Identity inspector, set the class to the view controller you created in your project.
In your custom controller class, create IBOutlets for every view (such as deleteButton) in the associated view you need to have access to. Create and synthesize the properties for every outlet.
Create IBActions for every event you want to register (such as addButtonClicked).
In the NIB, drag a line with your secondary mouse button from the File's Owner to the wanted outlet view and then select which connection you want to make. Repeat until all your IBOutlets are properly connected.
Drag a line with your secondary mouse button from the view you want to register events from to the File's Owner and then select which connection you want to make. Repeat until all your IBActions are properly connected.
Write your code for the controller.