UIViewController shouldAutorotateToInterfaceOrientation - objective-c

I had a question regarding shouldAutorotateToInterfaceOrientation:
I have a grid view controller and I have put a breakpoint in the autorotate method it see if the method was being called. Turns out, even if I rotate the device (testing on simulator), the method is not being called.
Can anyone suggest me how to investigate this problem? Thanks.

Ensure that your view controller is either set as the window's rootViewController, or it is contained within a container view controller that is set as that.
Your issue will be that it is not receiving the window notification which is passed to the root view controller, and then further down to each of its children, and then down to their children etc.
If you have made your own custom container view controllers, ensure they all forward the message on to their children appropriately. Somewhere in that chain is a break.

Related

How to get notification in view controller when bringSubviewToFront is called?

My application needs a notification in the view controller when I call bringSubviewToFront(). I tried viewDidAppear but it doesn't work (Obviously I shouldn't work because view is already in the stack). I have gone through the documentation of view & viewController but didn't find anything that can solve my problem. Is there any way to get view controller notified?
You won't get the viewDidAppear notification with bringSubviewToFront. It gets fired when you add the view as a subview or change the hidden property on the view. You must also make sure that your ViewController has been added as a child view controller to it's parent using
addChildViewController.

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.

addSubview: re-writes the navigation stack?

I'm working on a app which uses the controller containment pattern as described in the View Controller documentation in the iOS SDK.
I've written the controller container, and it works great. My controller is basically containing two sub views and it displays them both at the same time, sliding one over the other depending on what the user is doing. Works wonderful.
Now, I want to use this container controller in a navigation view. This is to get push segues to work. In effect, from my contained controllers, I want to be able to use the navigation stack, push a new controller on, and pop when the user is done.
However, I have noticed that if the navigation view is instantiated with my container controller as the root container, things fall apart.
In particular, I have noticed this:
In the iOS documentation, container controllers call addChildController: and then addSubview:. This seems to break the navigation stack, as the push segue does not work - it behaves like modal. I believe it does this because addSubview resets the navigation stack.
I confirmed this by replacing addChildController and addSubview with [self.navigationController pushViewController...]. I confirmed it is a problem with addSubview because I can reproduce the issue when I omit the call to addChildController.
When I do this, the navigation stack works properly. But of course, my container controller does not, as only the "most recently pushed" controller is visible.
I'm doing this because in my contained controllers, I want to push a new controller onto the stack, and when the user is done, I want to "pop" the stack, without reloading the "previous controller".
Using a modal segue reloads the previous controller; using a push controller does not.
I cannot find any documentation on the behavior of addSubview and it's effect on the navigation stack.
Thank you in advance for any light you guys can shed!
I'm having a bit of trouble completely understanding what you are doing, but I think that what you want to do is exactly what I'm doing.
I have a UINavigationController that has as its rootView a container UIViewController. That controller adds children per the normal methods. One of those children views pushes other views that may get popped.
One of those pushed views COULD message the appDelegate and make itself the rootViewController if it wanted to. In general, as long as you keep a strong reference to a view controller, you can remove it from whoever 'owns' it, and muck around with the navigationControllers viewControllers array to your hearts content.

Only support orientation for modal UIViewController

My app has a UINavigationController, it does not support rotation. However I want to show a modal view controller on top of the navigationcontroller that should support rotation. Is this possible? I tried to override shouldAutorotateToInterfaceOrientation on the view controller that is shown modally but that doesn't seem to work.
I think that in addition to shouldAutorotateToInterfaceOrientation of the view controller that is shown modally returning YES, your navigation controller's shouldAutorotateToInterfaceOrientation should be overridden to return YES when that modal view controller is showing, and NO otherwise.
You need to make sure your device generates device orientation notifications (UIDeviceOrientationDidChangeNotification):
make sure:
generatesDeviceOrientationNotifications is set to true
From the Apple docs:
"The window object does much of the work associated with changing the current orientation. However, it works in conjunction with the root view controller to determine whether an orientation change should occur at all and, if so, what additional methods should be called to respond to the change. If this controller is a container, it may rely on a child to decide whether the orientation should occur."
So if you root view controller (UINavigationController?) doesn't support rotations then this might be set to false when your app starts. In which case you will need to turn it back on when appropriate:
UIDevice myDevice = [UIDevice currentDevice];
[myDevice beginGeneratingDeviceOrientationNotifications];
I found the answer in another post: UIViewController inside a root ViewController not rotating
The key is
- (void)addChildViewController:(UIViewController *)childController
and
- (BOOL)automaticallyForwardAppearanceAndRotationMethodsToChildViewControllers

How return back info from a child to parent in a NavigationController

I wonder what is the proper way to get back some message from a child view.
I have a object that is edited in the child view. I wanna see in the TableView their modifications.
However, I don't know a clean way to do it (I don't like a singleton here).
Is possible get notified when the Child view dissapear and get some info on that?
You can use the UIViewController notifications viewWillDisappear: and viewDidDisappear: to be notified right before a certain UIView is about to disappear and right after it disappears respectively. Note that most of the various UIKit objects (including UITableView) are subclasses of UIView.
IMHO, the "correct" way would be to implement a custom protocol in the view's controller (probably navigation controller in your case) or the application delegate and have the child view communicate using it when it gets the viewWillDisappear and/or viewWillDisappear notifications (as mentioned in Adam's reply). Similarly, in the parent view you can refresh the necessary information in the viewWillAppear handler.
This way, the parent view is getting its data from the delegate and not directly from a specific child view, which maintains MVC in your design.
You could also issue a notification (using NSNotificationCenter) that the parent would be subscribed to listen for - that has the side benefit that other classes could be notified as well.
But if it's a pretty strict relationship where only the sub view and master table will care, you probably should set your table view controller as a delegate of the subview and have the subview call the delegate directly (a protocol as mentioned is a good idea for something like this).