UIViewController inside UIView not getting rotation delegation - iphone

I have a UIViewController's view inside my UIScrollView subclass. The problem is my UIViewController is not getting the willRotate delegate called when I rotate the device. This is probably because UIView does not have a rotation delegate implemented in it. What is the best way to solve this?
Basically the structure is I have a MainViewController in which it has a UIScrollView. Inside this UIScrollView I have a subviews, which is the view of a bunch of UIViewControllers. The issue now is, it's not getting rotation calls when I rotate. One way to deal with this is to delegate from the MainViewController to those respective UIViewController. Is there a better/elegant way to solve this?
I am adding it as a subview from my UIScrollView not my MainViewController and you can't do UIViewControllers containment from a UIView. Correct me if I am wrong

I think you're going against the MVC pattern. You can't have a controller inside a view; instead you should have a controller that mediates the communictaion between the view and the user's input. In your case you could set the scrollview as self.view of the MainViewController, and then add the viewcontrollers views as subviews.

Watch the video that I posted in my comment: https://developer.apple.com/videos/wwdc/2011/?id=102
Here is a short summary of view controller containment, which is the design you are looking for, not combining all your logic into one view controller or using delegation for something that is built into the SDK.
A view controller has a view and provides logic for that view and most likely some of it's subviews.
You might have a complex view hierarchy and complex logic for specific views in that hierarchy that warrant the view to have it's own view controller controlling it and it's subviews.
Say you have a MainViewController and it's view is a UIScrollView (or subclass). Inside that scrollview, you might have an assortment of complex views that warrant their own controller, so you have a class, SubViewController that has the subview of the scrollview as it's view.
SubViewController needs to have rotation and appearance method callbacks working correctly in order to implement your logic for the the subview and handle layout changes.
[mainViewControllerInstance addChildViewController:subViewControllerInstance];
But, wait. The subview is still not in the view hierarchy.
[mainViewControllerInstance.view addSubView:subViewControllerInstance.view];
You have successfully created a valid view controller hierarchy of two view controllers and set up the associated view hierarchy of their views.
You will now have the appropriate callbacks functioning, as MainViewController will forward them to SubViewController.
EDIT:
See the documentation for an over view of view controller containment: http://developer.apple.com/library/ios/#documentation/uikit/reference/UIViewController_Class/Reference/Reference.html

Related

Call willrotate method for added subview controller

I have added one view controller to my first view controller as aa subview by using self.view add subview:secondview now when I'll rotate the device
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration;
method calls for only parent view Now I also want to call that method for child view controller so i can make required changes in child view controller also.
So for that what I have to do??
-Thanks in advance.
In WWDC 2011 Session 102 on view controller containment, they mention that a failure to keep one's view controller hierarchy synchronized with the view hierarchy can result in rotation events problems. They explicitly point out that if you just grab a view controller's view and add it as a subview of the main view, without adding the controller, itself, to the view controller hierarchy, you won't get these rotation events. In that WWDC session, they also suggest that if you want to "future-proof" your app, you'll want to manage view controllers properly.
From a pragmatic perspective, this means that as you go from one view to another, that you really should be transitioning the view controllers. Most commonly this means using pushViewController or presentViewControllerAnimated (formerly presentModalViewController). Or you can use view controller containment (see that WWDC session or look at the very brief comments about containment in the UIViewController Class Reference). But don't just grab the view from another view controller and just add it as a subview of the current view.
If you pursue view controller containment, at a minimum, you could add your child view's controller to the hierarchy via:
[self addChildViewController:childController];
[childController didMoveToParentViewController:self];

UIViewController in a UIView

Can I load a UiViewController in a UIView in another UIViewcontrller.
suppose UIViewControllerA has a UIView named subuiview. Can I load UIViewControllerB into subbuiview?
Thanks!
Starting with iOS 5
"Container view controllers" have been added in iOS 5. You can add a view controller as a child of another one with addChildViewController:.
You also are responsible for adding its view to its parent's view.
Everything is well documented in the iOS SDK documentation: Implementing a Custom Container View Controller.
To add a child view controller:
childViewController.frame = ...
[self.view addSubview:childViewController.view];
[self addChildViewController:childViewController];
[childViewController didMoveToParentViewController:self];
and to remove it:
[self willMoveToParentViewController:nil];
[self.view removeFromSuperview];
[self removeFromParentViewController];
Prior to iOS 5
It's possible to load another view controller and add its view as a subview of another controller's view.
UIViewController *subController = ...
[self.view addSubview:subController.view];
Although it's not recommended by Apple's guidelines:
Each custom view controller object you
create is responsible for managing all
of the views in a single view
hierarchy. [...] The one-to-one
correspondence between a view
controller and the views in its view
hierarchy is the key design
consideration. You should not use
multiple custom view controllers to
manage different portions of the same
view hierarchy.
(from the View Controller Programming Guide)
Your sub-controller won't receive rotation events, or viewWillAppear, viewWillDisappear, etc (except viewDidLoad).
So Apple advises us to use a single view controller managing the entire view hierarchy (but doesn't forbid to use multiple ones).
Each view may still be a custom subclass of UIView. Maybe you don't need another view controller but rather a custom view.
[self addSubview:viewControllerB.view];
try this in the sub view
It has always been problematic to simply use addSubview to add a view controller's view as a subview of another's. It's especially bad when people use it to transition between views, rather than relying upon other, more robust, solutions like presentViewController or pushViewController.
If you really want to add one view controller's view as a subview of another's, iOS5 introduced "view controller containment". Containment is discussed in the View Controller Programming Guide as well as WWDC 2011 session 102. Bottom line, you want to ensure you keep your view controller hierarchy synchronized with your view hierarchy, by calls to addChildViewController, didMoveToParentViewController, etc. See the documentation and the video for specifics.
Well you cant technically load a viewcontroller. You can load a viewcontroller's view as a subview of any view.
You need to also retain the view controller incase you have any actions attached to it. Otherwise it may result in crashes.
addsubview:controller.view is the method you want to look at.

Creating an overlay view ontop of EAGLView

I am creating a game using OpenGLES.
Game consists of a view controller and the EAGLView.
I have created another view controller that I want to handle the extra view that go ontop of the EAGLView so things like menu and options.
I have a call from the EAGLView view controller to the extra view controller that adds an IBOUTLET UIView to the appdelegates window however its not appearing. The methods being called but no view is being added.
Probably a really easy and stupid question but I cant work it out.
Thanks for any help in advance
Ok I have done it a different way.
I use a view Controller called GameViewController to load up and i add its subview to the window in the appDelegates applicationDidFinishLaunching method
Then i call a method to add another view controllers view (my open gl view) to the subview. This means I can then put other views over the top.
I don't know why i didn't do this before to be honest
Thanks for your help
Can you be more specific with this sentence:
I have a call from the EAGLView view controller to the extra view controller that adds an IBOUTLET UIView to the appdelegates window however its not appearing.
One approach is to use navigation controller that could be initalized with EAGLView controller as root. So, you can push and pop in navigation controller another view controller that handles the game menus.
Another approach is to present menu as modal view controller. This can be invoked with presentModalViewController: in current EAGLView controller.

If I have a UIViewController in a UIScrollView how can I programmatically make the UIScrollview zoomToRect?

I have a scrollview that has a page control. The scrollview contains 3 views. Each view contains a view controller. In one of my view controllers I press a button and I want the scrollview to scroll to a specific location. But Im not sure how to accomplish that since the button is not in the UIScrollview but in one of the view controllers. Could anyone point me in the right direction with this? I have spent a lot of time trying to follow the view hierarchy to see if I can send a message to the scrollview for it to scroll. Any help is appreciated.
You can:
Add a delegate in your 3 inner View
Controllers that points to the View
Controller that holds your Scroll
View.
Create a method in the View
Controller that holds the Scroll
View that will call [scrollView
zoomToRect:] when called.
Access it from your 3 inner View
Controllers using the delegate.
If you need more information about delegation. check what is Delegate in iPhone?.

Using navigation controller of superview

I've made a custom view to which I add a custom button. This custom view goes as a subview to yet another view (Kal calendar for iphone) that I push into a navigation controller. Now the button in my custom view is connected to an IBAction in which I am not able to call upon the self.navigationController to pop the current view from.
I've tried the [[sender superview] navigationController] for a hierarchy of superview calls but it doesn't work that way either.
Any ideas please?
Thanks
A view typically has no knowledge of its view controller (and consequently, to its or its superview's view controller's navigation controller) because this would introduce a tight coupling between view and view controller that is usually unwanted and unnecessary.
The easiest way to solve your problem would be to have the view controller instead of the view handle the button's action. If that doesn't work for your design, consider designing a delegate protocol for your custom view and make your view controller the custom view's delegate. The view would then call the delegate method in the button's action method. This latter method is used a lot throughout Cocoa, e.g. by UIScrollView (UIScrollViewDelegate) and UITableView (UITableViewDelegate).