ViewController not responding to didRotateFromInterfaceOrientation - iphone

My view controller is not responding to didRotateFromInterfaceOrientation, despite that I have added following in my code:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return YES;
}
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
[self.popOver dismissPopoverAnimated:NO];
if (interfaceOrientation == UIInterfaceOrientationLandscapeRight) {
... My Custom Code...
}
}
Am I doing something wrong here?

If you can't inherit from UIViewController (which is unfortunate), you can use this:
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
Then register to start receiving UIDeviceOrientationDidChangeNotification notifications.

If your UIViewController is a child in some root view then IB does not add it as a child controller to the root controller by default. The easiest way to address this is to modify your root controller:
- (void)viewDidLoad
{
[super viewDidLoad];
[self addChildViewController:(UIViewController*) self.yourChildController];
}
This should do the trick. Now your child controller will be receiving both:
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration;
and
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation;
messages.

I think the real answer here (more accurately the answer to the linked question) is that you need to call
[super didRotateFromInterfaceOrientation:fromInterfaceOrientation];
in your subclass implementation of the didRotateFromInterfaceOrientation method. For example:
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
[super didRotateFromInterfaceOrientation:fromInterfaceOrientation];
// Then your code...
}
This is not mentioned in the apple documentation but caused some serious and unexplained problems for me when omitted...

Related

motion callbacks never called

I'm trying to make a shake events.
I tried:
1) How do I detect when someone shakes an iPhone? (posts of Kendall, and Eran)
2) motionBegan: Not Working
but nothig helps.
My View becomes first responder, but motionBegan/motionEnded never called.
Is there some additiol settings must be done, or i'm missing somethig? My iOS SDK is 4.3.
I have a class of UIView:
#import "ShakeView.h"
#implementation ShakeView
- (BOOL)canBecomeFirstResponder {
return YES;
}
- (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event {
NSLog (#"123");
if ( event.subtype == UIEventSubtypeMotionShake ) {
NSLog(#"Shake!");
}
if ([super respondsToSelector:#selector(motionEnded:withEvent:)]) {
[super motionEnded:motion withEvent:event];
}
}
#end
In my ViewController's xib class of View is ShakeView.
my ViewController pushed:
Wheel *secondViewController = [[Wheel alloc] initWithNibName:#"Wheel" bundle:nil];
[self.navigationController pushViewController:secondViewController animated:YES];
[secondViewController release];
In my ViewController:
- (void) viewDidAppear:(BOOL)animated
{
[self.view becomeFirstResponder];
[super viewWillAppear:animated];
NSLog(#"%d", [self.view isFirstResponder]);
}
- (void) viewWillDisappear:(BOOL)animated
{
[self.view resignFirstResponder];
[super viewWillDisappear:animated];
}
It logs "1", so it IS first responder. But it logs nothing else.
I spend a half day on this few lines of code, and I have no more ideas. Do anyone knows how to solve it?
Thanks.
This is much too late to help SentineL, but I was having the same problem and I like his question because it is clear that he has all the relevant code in place -- except one crucial line, in the application delegate's didFinishLaunching:
[self.window makeKeyAndVisible];
This is very hard to debug, because even without this line, everything else will be fine. Your gestures will work, your controls will respond, you will be able to make your view first responder (as SentineL checked) -- but your subclassed window or view or view controller will never receive the motion events.
Which doesn't make sense to me. Why would makeKeyAndVisible affect the accelerometer but not gestures? Hopefully some more experienced user can answer that.
P.S. If you use this code as an example, I would recommend that you omit the super respondsToSelector conditional. Of course it responds to the selector; you're overriding it.

When to use layoutSubview in iOS

I am writing iOS application for iPad that require custom layout.
The layout from portrait and landscape are totally difference, so it can't be solve by using UIAutoResizingMask.
I try to use the layoutSubview Method, but I detected that layout subview is called a lot (from UIScrollView).
How can i reduce the layoutSubview call to optimize the code , or I should call it by my self when ever the device is rotated.
Thank.
For different landscape and portrait design use view controllers methods such as
-(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration;
-(void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation;
-(void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration;
If you create your custom view depending on current orientation, check this orientation by UIDeviceOrientationDidChangeNotification notification and write appropriate code.
in one of the init~ methods:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(didChangedOrientation:) name:UIDeviceOrientationDidChangeNotification object:nil];
And action
- (void) didChangedOrientation:(NSNotification *)sender{
UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
if (UIDeviceOrientationIsPortrait(orientation)){}}
The fact that layoutSubviews gets called by a child UIScrollView is very unfortunate, but there's an (ugly) workaround:
#interface MyClass : UIView {
BOOL reallyNeedsLayout_;
}
#end
#implementation MyClass
- (void)setNeedsLayout
{
[super setNeedLayout];
reallyNeedsLayout_ = YES;
}
- (void)setFrame:(CGRect)rect
{
[super setFrame:rect];
reallyNeedsLayout_ = YES;
}
- (void)layoutSubviews
{
if (!reallyNeedsLayout_) return;
reallyNeedsLayout_ = NO;
// Do layouting.
}
#end
Not the best solution but seems to work reasonably well.
You should not do expensive calculations in layoutSubviews:
Speaking from experience I would personally only adjust your layout based upon deviceDidRotateSelector notifications.
I have an updatePortrait method and an updateLandscape method and call whichever is necessary.

shaking iphone in 4.0+

How do I use shake-events in iOS 4.0+? I tested this solution but isn't working in 4.1. Is it possible that something changed or am I doing someting wrong? motionBegan: Not Working
From this SO question How do I detect when someone shakes an iPhone?
The main trick is that you need to have some UIView (not view controller) that you want as firstResponder to receive the shake event messages. Here's the code that you can use in any UIView to get shake events:
#implementation ShakingView
- (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event
{
if ( event.subtype == UIEventSubtypeMotionShake )
{
// Put in code here to handle shake
}
if ( [super respondsToSelector:#selector(motionEnded:withEvent:)] )
[super motionEnded:motion withEvent:event];
}
- (BOOL)canBecomeFirstResponder
{ return YES; }
#end
You can easily transform any UIView (even system views) into a view that can get the shake event simply by subclassing the view with only these methods (and then selecting this new type instead of the base type in IB, or using it when allocating a view).
In the view controller, you want to set this view to become first responder:
- (void) viewWillAppear:(BOOL)animated
{
[shakeView becomeFirstResponder];
[super viewWillAppear:animated];
}
- (void) viewWillDisappear:(BOOL)animated
{
[shakeView resignFirstResponder];
[super viewWillDisappear:animated];
}
Don't forget that if you have other views that become first responder from user actions (like a search bar or text entry field) you'll also need to restore the shaking view first responder status when the other view resigns!
This method works even if you set applicationSupportsShakeToEdit to NO.

UIInterfaceOrientation method not working

Call is not going into the UIInterfaceOrientation delegate method please help
here is the code
- (BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
{
return YES;
}
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
if (toInterfaceOrientation == UIInterfaceOrientationPortrait)
{
NSLog(#"potrait");
}
else
{
}
}
Is your view controller inside another view controller?
Look for Technical Q&A QA1688 Why won't my UIViewController rotate with the device? in your developer documentation
That will give you a hint of why it isn't working in your case.
I had this problem last week, and here is what I discovered. If you are using a tab bar, then you must have
- (BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
{
return YES;
}
in every view controller that is added to the TabBarController in order for any of them to rotate. If you only want certain tabs to rotate, you can still achieve this by adding
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
}
There may be a similar resolution if you are using a NavigationController, but I haven't run in to that problem yet.

for the query of methods of rotation

I have 1 UIViewController.
in that i wrote,
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
NSLog(#"A");
} in UIViewController.
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
NSLog(#"b");
}
but this method is not called
why is it so?
You may need to do two things:
Tell device to track orientation changes: call [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
Implement your View controllers -shouldAutorotateToInterfaceOrientation method - return YES for orientations you want to support.