custom UIWindow orientation - iphone

I needed to see touch events on my window, so I subclassed UIWindow to make my a MYWindow class. I am overriding the sentEvent function to receive the touch events on the window and all of that is working just fine. I did the following to achieve this:
self.window = [[MYWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
[window makeKeyAndVisible];
The issue I am facing is that when I do this, the viewControllers that are on this window won't rotate anymore. If I were to use a regular UIWindow, they all work just like I intended them to work. Obviously, something is wrong with my setup.
I was looking through UIWindow header file and there is a method called
- (void)becomeKeyWindow; //override point for subclass, Do Not call directly
Am I suppose to implement this in my custom UIWindow class just like I had to implement the sendEvent: method? Please point me in the right direction with this.
Thanks in advance guys.

I figured out what the issue was. I was creating a delegate on the custom window and called it "delegate" which was causing the issue. Naming it to "aDelegate" solved the issue. thanks for all your help.

I'm only guessing here, but I'd presume it is because you made MYWindow the key window now (even if it is transparent) and shouldAutorotateToInterfaceOrientation: is part of UIViewController class, not UIWindow.
So even though you can see your other views, they are not getting their rotation events called on them anymore.
Instead of making it a UIWindow subclass, why not implement those touch events on a UIView that gets added to your view that needs the touch events handled? You can make it transparent as well, and just keep the rotation handled at the UIViewController level?

Related

UIWindow UIView addSubview issue

Every video tutorial and book I have read displays the following code to add a UIView to the UIWindow.
[window addSubview:self.viewController.view];
My understanding of the above code is that a "View" (which is an instance of a UIView) is added to the window (Which is an instance of UIWindow). Let me break it down (According to my understanding):
window (UIWindow)
addSubview (method to add a View to a window)
Self.viewController.view (simply returns an instance of a "view" which is already instantiated within the UIViewController class.
The first problem I have is that I could not find the method "addSubview" in the UIWindow class reference document on apples site. However somebody kindly pointed out to me that UIWindow inherits addsubview method from UIView. thats all fine, but why do all the book and online documents state that the addsubview method adds a view to the window - but how can that be? really confused. Can somebody please explain step by step what this code is doing? If UIWindow inherits the addsubview method of UIView then how can it go back up the inheritance tree? really lost. What I really need is small example code with diagrams of what is happening step by step. would be REALLY greatfull. many thanks
Think of a window as a view that's associated directly with a screen or drawing object.
In the above example window.view is not correct. a window does not contain a view, it is a view with additional behavior.
Assuming that you are loading a UIViewController from a NIB file, the view associated with the viewController will be instantiated by accessing the view. So ...
You might see code like
MyViewController *vc = [MyViewController alloc]initWithNibName:#"MyNibFile" bundle:nil]autorelease];
[window addSubView:vc.view];
[window makeKeyAndVisible];
View is simply a super class of Window so any public view method is available to you.
Generally the window in your AppDelegate object is instantiated when the MainWindow.xib file is loaded.
You should see something like
#property(nonatomic, retain) IBOutlet UIWindow *window;
in your AppDelegate header file . (The IBOutlet directive tells the initialize the window object when the nib file is loaded.
Just remember, a UIWindow is simply a UIView with additional behaviors and data.
Hope this helps.
"However somebody kindly pointed out to me that UIWindow inherits addsubview method from UIView. thats all fine, but why do all the book and online documents state that the addsubview method adds a view to the window - but how can that be? really confused. Can somebody please explain step by step what this code is doing? If UIWindow inherits the addsubview method of UIView then how can it go back up the inheritance tree?"
That's it. I think you are not understanding what inheritance is. The metaphor is "is a". A UIWindow "is a" UIView. It has everything a UIView has, and more. One thing a UIView has is the ability to addSubview. Therefore a UIWindow has that ability too. It doesn't need any other UIView to do it for it. It is a UIView. It can do it itself.
try
[window.view addSubview:self.viewController.view];
That is off the top of my head, so it may not be completely accurate.

iPhone SDK - Forwarding touches from a UIViewController to a subview

I have a UIViewController with a subclass of UIView on it called customSubView1. Then on customSubView1 I have another subclass of UIView called customSubView2.
I can capture all the events for touches on all the subviews when I put touchesBegan/touchesMoved/etc in the UIViewController class. But I want to be able to process them in my custom classes.
I keep reading that the UIViewController class needs to 'forward' the touch events to the subviews, but I haven't been able to find any example code to do this. Does anyone have any idea?
Many thanks,
Brett
Implement the touches... methods in your views.
Try to set for you UIView object userInteractionEnabled property:
myUIView.userInteractionEnabled = YES;

iPhone - Accessing superviews methods?

So essentially I'm inserting "startViewController" into "mainViewController" now of course I can access startViewControllers methods from mainViewController but I was wondering how to do the opposite? Occasionally startViewController will need to call something in mainViewController and I was just wondering how I do this?
Thanks in advance.
Add an ivar of your mainViewController to your startViewController and set this when showing the view.
Or you can design a nice clean protocol, and make one view the delegate of the other.

Custom UIViewController is not responsive to device rotation

I have a custom UIViewController, which is the only subView of UIView. The UIViewController contains delegate function:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return YES;
}
This function is called once when the application starts and is never called again when the device is rotated. I also notice that the willRotateToInterfaceOrientation function is never called. I pretty much commented out all the content in the UIViewController but it is still not responding to device rotation.
I ended up solving my own problem by starting from stretch to create a brand new UIViewController and made sure it was responsive to the device rotation. I then brought in my code piece by piece and checked the rotation. In the end, I found the root cause. In my custom UIViewController, I had
- (id)initWithFrame:(CGRect)theframe {
if (self.view = [super.view initWithFrame:theframe])
It worked find excpet it did not respond to device roation even though I did not call the init function. The solution is simple. Add [self init] in the initWithFrame function. Thank you all for responding.
Your code looks correct. I suspect it's something in your .xib file (like the wrong object type for "File's Owner"), so that perhaps your view controller subclass isn't being instantiated at all. Put some logging into viewDidLoad and make sure it's getting called.
Try doing a test app that just tests the rotation problem. This will help isolate your issue.
You may need to implement that method in the controller of the parent UIView, as it seems your view is enclosed in another view.

UIViewController created with initWithNibName: bundle: or via an IBOutlet behave differently

I found a strange behavior, and would like to be explained what assertion I am making that is wrong.
In an AppDelegate class of a freshly created WindowBased project, I am adding a UIViewController to the window.
I can do it two different ways:
- with an IBOutlet. In IB, I simply instanced an UIViewController, set its class to TestViewController and connected it (scenario A of the code).
- creating the UIViewController with code (scenario B).
- (void)applicationDidFinishLaunching:(UIApplication *)application {
#define USE_IBOUTLET YES // Comment this line to switch to scenario B
#ifdef USE_IBOUTLET
// Scenario A
[window addSubview:theTestViewController.view];
[window makeKeyAndVisible];
#endif
#ifndef USE_IBOUTLET
// Scenario B
TestViewController *theTestViewControllerProgrammatically;
theTestViewControllerProgrammatically = [[TestViewController alloc] initWithNibName:nil bundle:nil];
// According to Apple: "It is a good idea to set the view's frame before adding it to a window.", so let's do it
[theTestViewControllerProgrammatically.view setFrame:[[UIScreen mainScreen] applicationFrame]];
[window addSubview:theTestViewControllerProgrammatically.view];
[window makeKeyAndVisible];
#endif
}
As I did not do any customization of the object in IB, I should have the same behavior in both scenario.
Scenario A, using the IBOutlet works as expected.
But the scenario B has the following problems:
- The view is not at the right position (20 pixels to high, and covered by the status bar).
- The view doesn't resize properly (for example, try to toggle the In Call Status bar)
Why?
Zip archive of the project here if you want to reproduce the problem: http://dl.dropbox.com/u/1899122/code/ProtoWindowBasedStrangeness.zip
This is going to sound really silly after my long-winded answers, but the problem you're having is simple to fix (programatically).
This line:
[theTestViewController.view setFrame:[[UIScreen mainScreen] applicationFrame]];
Should actually be:
[theTestViewControllerProgrammaticaly setFrame:[[UIScreen mainScreen] applicationFrame]];
You were setting the frame for the VC set by IB, not by the one you created programatically.
Anyway - it's worth noting that all my comments still apply! There are still a few things you'll have to do programmatically if you don't use IB's controller objects (for example, setting up the navigation bar items)
Paul
I have been having a very similar problem to you in that I noticed VC objects are not all created equal! The problem I'm having is setting the navigation bar items, I just can't seem to do it when File's Owner is a view controller object that I instantiate programatically. It only works if I unarchive IB's controller objects.
I downloaded your project and had a play around with it, and it got me thinking some more about what might be going on. I think I can provide a reasonable answer, but not sure if there is a simple solution...
What I believe is going on is that Apple have created these controller objects in IB that are slightly more specialised. One suggestion this might be true is that IB VC objects have an attribute you can set that has no direct corresponding property for a UIViewController class that I can see, so IB's controller objects may have some additional functionality that non-IB UIViewController subclasses can't take advantage of. Given that objects in an .xib are complete 'freeze-dried' objects, Apple may have included all kinds of private attributes we can't see or use in their IB versions of them - this may have some effect on how the objects are initialised.
For example, in your MainWindow.xib, select the IB VC object and you can set attributes on it from the Inspector Palette, such as "Resize View From NIB". If you un-check this and re-run your app, you'll see the VC appear exactly as it does in scenario B. As you can't check this item when from the File's Owner attributes (even though it is as a UIViewController), you're unable to take advantage of whatever is being done by the view controller to give you the behaviour you want.
The result of this is that when you use TestViewController.xib to initialise your VC object in code, none of the IB specific attributes of a VC are set, therefore a bog-standard UIViewController is created, and so things like the "Resize View From NIB" attribute and setting up the navigation items have to be implemented yourself.
I've not yet found a way to take advantage of the functionality that IB's view controllers have when I instantiate them using initWithNibName:bundle:nibBundle (I'm guessing it's all private stuff we can't access), but hopefully this might have given you a starting point...
Of course, I could be completely wrong and someone will make me look like a complete idiot!
Paul
Probably in case B that view is not aware of the presence of a status bar. You need to resize it accordingly and adjust its position to take the status bar into account. That is done by changing the frame (size) and bounds (location) properties of a UIView.