The relationship between UIViewController and UIView - objective-c

I'm trying to understand how these two are connected. Every time you make a UIViewController does it also automatically come with its own UIView?
Also are these from Cocoa or Objective-C?

UIViewController is a Cocoa Touch class built for the purpose of managing UIViews. It expects to have a view hierarchy, but you don't "automatically" get a view (this is slightly inaccurate; see edit below). Usually you will obtain views by calling initWithNibName on your view controller.
There is some built-in magic in Interface Builder which knows that if File's Owner is a UIViewController (or subclass), there is a property called view. That's about it.
Once you have linked a view controller and a view, the view controller does a fair amount of work for you: it registers as a responder for view touch events, registers for device rotation notifications (and handles them automatically, if you wish), helps you take care of some of the details of animation, and handles low-memory conditions semi-automatically.
Edit: correction—if you don't call initWithNibName or set the view property manually, the view property getter will invoke loadView if view is nil. The default implementation of loadView will see if you've set nibBundle and nibName and attempt to load the view from there (which is why you don't have to call initWithNibName, most of the time), but if those properties aren't set, it will instantiate a UIView object with default values. So technically, yes, it does automatically come with its own UIView, but most of the time that's of little value.

UIViewController doesn't automatically come with a view. You have to make a view in the -loadView method. By default, this loads the view from the nib file you've specified. You can also override this method to make a custom view if you prefer not to use a nib.
Also, the view is not created right when the UIViewController is created. UIViewController uses a technique known as lazy-loading to defer the creation of a view until the view is actually accessed for the first time.

Related

What's the advantage of using UIViewController as owner of xib?

Most of the time, owners of xib is a UIViewController.
I sort of use it my self.
Still I am confused why.
I suppose, the viewDidLoad and viewWillAppear is kind of the main selling point.
Is that it?
What are the advantage of using UIViewController as owners of an XIB?
A UIViewController object is the main way for views to appear within an iOS window.
Apple provides this as a fundamental, foundational building block (along with so many others) which you can use to build upon quickly and get your app out to market.
And when you subclass UIViewController, you're able to do lots of beautiful customizations which can be collected and eventually turned into (hopefully decent) products. When you subclass a UIViewController, you need to set the "owner" of a XIB file to that subclassed view controller (e.g. ThioViewController), so that way the app knows what object (and user interface) is being instantiated.
Hopefully this isn't too super abstract of an explanation.
First, spend a bit time to understand MVC http://en.wikipedia.org/wiki/Model–view–controller
This is the milestone of Objective-C (not only) development.
UIViewController is controller for all your views (inside this viewController). It provide starting point for you to create views on the screen, manipulate the views, handle actions from views etc.
You can create UIViewController programmatically.
XIB is representation of the screen which you can comfortably operate in Interface Builder to create and customize design of your application screen or one of the screens.
Since XIB represent the screen(view) it must be the controller which controls all the view on the screen - UIViewController or UINavigationController or other type of controller depending of your needs.
Most of time you will subclass UIViewController and use it to achieve you goals.
UIViewController have several subclasses which inherit directly from it (UINavigationController, UITabBarController).
Also UIViewController hav several methods (some of them)
-(void)viewDidLoad
This method is called after the view controller has loaded its view hierarchy into memory. This method is called regardless of whether the view hierarchy was loaded from a nib file or created programmatically in the loadView method. You usually override this method to perform additional initialization on views that were loaded from nib files.
and
-(void)viewWillAppear:(BOOL)animated
Parameters
animated
If YES, the view is being added to the window using an animation.
Discussion
This method is called before the receiver’s view is about to be added to a view hierarchy and before any animations are configured for showing the view. You can override this method to perform custom tasks associated with displaying the view. For example, you might use this method to change the orientation or style of the status bar to coordinate with the orientation or style of the view being presented. If you override this method, you must call super at some point in your implementation.
Please check Apple documentation for more information
https://developer.apple.com/LIBRARY/IOS/documentation/UIKit/Reference/UIViewController_Class/Reference/Reference.html

Why does self.view call subview setter method?

I have a custom view controller with several subviews. Each of those subviews is connected to the view controller's .m file via IBOutlet properties. Those subviews have custom setters that adjust size of the other subviews depending on whether that subview is or is not displaying content.
Now it seems that these custom setters are being called by initWithCoder: prior to viewDidLoad being called. (I hope/assume this is normal.)
My issue is that calling self.view accesses the setter methods for self.view's subviews. My current understanding is that this should not be necessary. Can someone explain what's going on here? I'd rather this not happen as I'm not intending to set anything by accessing self.view.
Here is the code: https://github.com/kenmhaggerty/Sandbox
Calling self.view on a view controller causes it to load its view from the nib, if it hasn't already done so. This instantiates all objects in the nib (using initWithCoder:) and sets the values of any outlets (using your accessor methods). It then calls viewDidLoad, by which point everything in the nib will exist.
Your outlet setter methods are probably not an appropriate place to be making layout adjustments. Either use a constraint-based layout which will automatically adapt to changes in size of the subviews, or use viewDidLayoutSubviews, or use the methods you are using to pass model information to those subviews.

When will viewWill/DidAppear/Disappear is called anyway and how exactly does it work?

I understand that viewWillAppear will be called when duh.... when the the view is about to appear.
But how does IOS know that a controller's view is about to appear?
When exactly that and how it is implemented?
For example, does the childController.view check first that window is one of it's super ancestors? Does the view has a pointer to it's controller? How exactly that works? Does everytime a view is added it check whether it's window is it's super ancestor and whether it is the view outlet of a UIViewController?
For example, if I add childcontroller.view but not to a subview of any view that's being called. Will viewWillAppear called?
Does the childController need to be the a child of a parentController so that viewWillAppear of the childController will be called when the parentController's viewWillAppear is called automatically?
The view is loaded by your controller using the - (void)loadView method. This method is implemented to load a blank view or a view from a nib/storyboard. You only need to override it if you really need to create a view hierarchy from scratch.
All of the magic happens when the value of the view property is first requested and the controller detects the value is nil. All of the life cycle method calls are handled by the UIViewController. There is nothing you need to do other than implement the methods if you need them. Remember one thing: There is no guarantee the view has been loaded until the - (void)viewDidLoad method has been called.
Everything I've learned about controllers how they work has come from the View Controller Programming Guide.

Access NSWindow's Element via Child NSView/ViewController

Is it possible to access a NSWindowController's element from a child NSViewController?
Essentially I have a NSProgressIndicator that spins on the bottom corner of the NSWindow. This works because my WebView is in my NSWindowController instead of my NSViewController.
I want to break the logic apart now but I'm having trouble understanding how I'd access these elements from my View Controller.
Thanks!
You can't connect an outlet from one NIB to an object in another and the desire to do so indicates a problem with your design. If the view is so intimately connected to other things in the window, maybe it shouldn't be separated out into a different NIB.
A view should only go into a separate NIB when it makes sense as a self-contained unit. It should represent and manipulate its controller's representedObject and not much more. The controller might have a delegate that it informs about what's being done and asks to make customizing decisions.
Maybe you can continue to use a separate NIB if you adopt that sort of design. Perhaps the window will have a reference to some model object. It would configure the view controller to use that model object as its represented object. And perhaps the progress indicator would be bound to that same model object. Then, as the view manipulates its represented object, it would indirectly also affect the progress indicator.
Another option would be for the window controller to set itself as the delegate for the view controller and your view controller could invoke it at appropriate points to inform it of things going on in the view. Then the window controller could do whatever was appropriate to the progress indicator or other stuff in the window outside of the view. This hypothetical delegate is something you would have to add to the view controller class and you'd design its protocol.

Handling touch event logic in Subview or ViewController

I have a series of UIView subclasses that are added as subviews. Each subview can be dragged and dropped. When they are dropped (touchesEnded), I need to run a method in the viewController to do some work. I currently have the touchEvents handled in each subview class. Should I be handling these touch events in the viewController or should I be passing a pointer to the parent viewController as a property of each class I have added as subviews?
UPDATE: Or is this a job for NotificationCenter?
UIViewController is a subclass of UIResponder, and instances are automatically inserted in the responder chain behind the views they control. As a result, you can implement the same event methods in subclasses of UIViewController as in subclasses of UIView, and they will 'just work'; that is, they'll be called automatically.
So if your view controller needs to respond to -touchesEnded:withEvent:, just implement the method directly in your UIViewController subclass. If the view also needs to do something in response to the event, you can always send it a message from within your -touchesEnded:withEvent: (or whatever) implementation.
You might try delegating your desired touch handling event from your uiview subclass to the uiviewcontroller using a delegate protocol. The view controller can set itself as delegate as it instantiates or adds each subview.
In MVC paradigm, if you want to handle a touch that's specific to a V view's internals (button appearance/location), then you might want to handle that touch in the V view, but if the touch effects some state outside the view (it's position in a bigger window, etc.) you might want to pass handling that touch up to the C controller to set state in the M model.