Callback method on auto rotation, iOS and iPad - iphone

I am working on iPhone game, i was curious to know if there is a call back function tht gets called when the device forces auto rotation on the game, so that i can change the HUD elements.
Or shd i run infinite loop that checks if the app has rotated in a different thread? problem is i dont think this is an effective way. Does anyone have any good solution for this.

All you have to do is this:
In your didfinishlaunching write this
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(didRotate:)
name:UIDeviceOrientationDidChangeNotification object:nil];
and then copy the following callback method
- (void) didRotate:(NSNotification *)notification
{
UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
if (orientation == UIDeviceOrientationLandscapeLeft)
{
NSLog(#"Landscape Left!");
self.isLandscapeLeft=1;
}else if(orientation == UIDeviceOrientationLandscapeRight){
NSLog(#"Landscape Right!");
self.isLandscapeLeft=0;
}
}
Likewise you can check orientation for potrait mode,face-up,face-down,upside down and landscapeleft and landscape right orientation.:)

Yes there is, as long as the device is not orientation locked you can register to listen to
UIDeviceOrientationDidChangeNotification
which can be seen here http://developer.apple.com/library/ios/#documentation/uikit/reference/UIDevice_Class/Reference/UIDevice.html
If you want to overcome the possibility of the device being orientation locked, then you have to manually monitor the accelerometer of the device.
In a game where orientation is essential, manually monitoring is recommended, since the first method has a little delay.

Related

Notification listeners causing crashes

I'm using the following code to detect/listen for when the iPad changes device orientation.
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(didRotate:)
name:#"UIDeviceOrientationDidChangeNotification"
object:nil];
This calls my didRotate: method when something changes. In my didRotate: method, I use UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation]; to figure out what the orientation is, and apply my code accordingly.
However, in real life testing, I noticed that didRotate: gets called every second if the iPad is in a person's hand. It appears the listener is literally listening for every little tilt and shift in the iPad, which obviously happens a lot in a person's hands (as opposed to flat on a desk).
Any ideas on how I can fix this? I could change my code to use interface orientations, but I've been having trouble with it for whatever reason. Thank you.
*UPDATE: This listener is created in my UIImageView subclass. There are about a dozen or more on the screen. I have added [[UIDevice currentDevice] endGeneratingDeviceOrientationNotifications]; to my removal methods for when I remove an instance. That helps explain why didRotate kept showing up so much (my error).
However, I have narrowed down crashes: whenever I remove this an instance of this subclass, and rotate my iPad, I crash. Sometimes I get weird messages like [__NSArrayM didRotate]: is unrecognized selector (and other wierd objects like UIPanVelocity...something). Is my listener still listening after the instance is removed?
FIXED: Thank you for your help. I finally noticed what was wrong. I was removing the instance without removing the observer and ending notifications. Adding following code into my instance removal methods fixes my problem:
[[UIDevice currentDevice] endGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter] removeObserver:self];
I'm guessing that you add observers repeatedly and never remove them. This means that the same entry point may get invoked multiple times for a single event. It also means that when the "self" object goes away you get a crash.
The notification is only sent if the device changes from one orientation to another orientation - it doesn't get fired more times than necessary.
UIDeviceOrientation has 2 more orientations than UIInterfaceOrientation. It has FaceUp and FaceDown. Possibly it is these that are getting triggered, and you're not interested in them.
typedef enum {
UIDeviceOrientationUnknown,
UIDeviceOrientationPortrait,
UIDeviceOrientationPortraitUpsideDown,
UIDeviceOrientationLandscapeLeft,
UIDeviceOrientationLandscapeRight,
UIDeviceOrientationFaceUp,
UIDeviceOrientationFaceDown
} UIDeviceOrientation;
Maybe you would prefer to listen for UIInterfaceOrientation changes in the view controller that is currently onscreen.
typedef enum {
UIInterfaceOrientationPortrait = UIDeviceOrientationPortrait,
UIInterfaceOrientationPortraitUpsideDown = UIDeviceOrientationPortraitUpsideDown,
UIInterfaceOrientationLandscapeLeft = UIDeviceOrientationLandscapeRight,
UIInterfaceOrientationLandscapeRight = UIDeviceOrientationLandscapeLeft
} UIInterfaceOrientation;
.
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration

willRotateToInterfaceOrientation not getting called

I have an issue when playing video while using the c "willRotateToInterfaceOrientation" function. Initially, I have my main view set on the landscape mode. The video is playing but then I tried to rotate it to portrait mode my project doesn't call the "willRotateToInterfaceOrientation" but when I tried to rotate it back to the landscapeleft mode and then rotate back again to the portrait mode it's just the time the "willRotateToInterfaceOrientation" is called. can anyone please help me? thanks
Try this instead of implementing code in willRotateToInterfaceOrientation.
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
NSNotificationCenter* notifCenter = [NSNotificationCenter defaultCenter];
[notificationCenter addObserver:self
selector:#selector(orientationChanged)
name:UIDeviceOrientationDidChangeNotification
object:nil];
Add the following method
-(void) orientationChanged
{
//Copy code from your willRotateToInterfaceOrientation method here.
}

UIDeviceOrientationDidChangeNotification doesn't work while device is on table?

Hi there i have a problem,
In my AppDelegate i have used method beginGeneratingDeviceOrientationNotifications to start notify me when device starts rotating.
It works fine if i hand-held my ipad but when it is kept on table it doesn't work as expected.
it fires UIDeviceOrientationUnknown notification.
Also this notification gets started after UI launches not on splash screen.
following is my code:
if([[[PulseUIFactory Factory] GetUICreator] IsIPad])
{
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(orientationChanged:) name:UIDeviceOrientationDidChangeNotification object:nil];
}
current device stars giving proper values.
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
then some where i launches my UI as
[self Launch_UI];
but notification starts responding after [self Launch_UI]; call even if notification is registered before its call...
Please any help is appreciable!!!
When you place your device on a table, [[UIDevice currentDevice] orientation] will return UIDeviceOrientationFaceUp. Then if your device remains sitting on the table face up, it doesn't matter how you rotate it on the table, the current device orientation will still be UIDeviceOrientationFaceUp.
If the device has issues determining the orientation, you may get UIDeviceOrientationUnknown. See this tutorial on how to handle device rotation using UIDeviceOrientationDidChangeNotification.
Regarding your notification only firing after the UI is loaded, the UIDeviceOrientationDidChangeNotification will only fire when the device is rotated. So if you are not rotating your device until after the UI loads, you wont get a notification. If this is not the cause of the issue, I'd have to see more of your code to have a better idea of what is going on.

execute method when iPhone enters landscape mode

Is there a delegate that will get called when the iPhone enters landscape or portrait mode? I need to change the style and place objects in a different place when the iPhone get's rotated. Do I have to do this with the accelerometer? Moreover if there exist such a delegate do I have to create the connection in interface builder. I am new to objective-c...
Register to listen for the orientation change notification.
UIDevice *device = [UIDevice currentDevice];
//Tell it to start monitoring the accelerometer for orientation
[device beginGeneratingDeviceOrientationNotifications];
//Get the notification centre for the app
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
[nc addObserver:self selector:#selector(orientationChanged:) name:UIDeviceOrientationDidChangeNotification
object:device];
Implement orientationChanged: method, which will be called when the device change the orientation. you could put code to check the orientation type and called your method.
- (void)orientationChanged:(NSNotification *)note
{
NSLog(#"Orientation has changed: %d", [[note object] orientation]);
}
Remove notification in dealloc.
[[NSNotificationCenter defaultCenter] removeObserver:self];
[[UIDevice currentDevice] endGeneratingDeviceOrientationNotifications];
Check the blog post
Reacting to iPhone's orientation
Implement didRotateFromInterfaceOrientation in your view controller
-(void) didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
You can get UIDevice to generate notifications for orientation events. See the documentation for UIDevice.
If you need to detect the change at any moment, you might consider calling -beginGeneratingDeviceOrientationNotifications in your app's delegate.
Also, if you are using UIViewControllers, there are
shouldAutorotateToInterfaceOrientation:
willRotateToInterfaceOrientation: duration:
didRotateFromInterfaceOrientation:

iPhone - too sensitive rotation detection

I have a UIActionSheet based class. The ActionSheets created by this class are designed to vanish if a device orientation rotation is detected.
So, when this class begins I have
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(didRotate:) name:UIDeviceOrientationDidChangeNotification object:nil];
and on the didRotate: i have the dismiss, that sends the ActionSheet away.
The only little, tiny problem is this: any vibration makes the actionSheet dismiss. Even tapping with a little bit more strength will make the popoup dismiss. Even if you are typing inside the actionSheet.
I don't have any accelerometer or coremotion enabled.
Any clues?
thanks
EDIT
I have discovered that the problem is that initially the orientation is being reported as UIDeviceOrientationUnknown and the trepidation makes it report the correct orientation. As UIDeviceOrientationUnknown is different from the correct orientation, this is seen as a rotation change...
Now I am doomed.
It's difficult to solve this cleanly, because the best methods for detecting the type of rotation you're interested in are called on UIViewController rather than UIView. In UIViewController you have willRotateToInterfaceOrientation:duration:, which tells you that an autorotation is about to occur. This method is on UIViewController because the controller has the responsibility of allowing or refusing autorotation. In order to convey this information to your view, you can post an NSNotification whenever a rotation is about to begin. Then, your UIActionSheet subclass can listen for this notification and shape itself appropriately. Alternatively, you could add a method to your subclass to notify it of rotations directly. It depends on how often you need to listen for autorotation in UIView subclasses and also how strong your need for reuse is.
just check for which interfaceOrientation you're having. since iOS something, PortraitUp and facedown are supported interface orientations. What's happening to you is that portrait (when lying on a table) is switching to face-up and vice-versa. Just check for that. Please be careful, you're looking at UIDevice Orientation, which is NOT UIInterfaceOrientation!
In my case, I was doing
if(orientation == UIDeviceOrientationLandscapeLeft || orientation == UIDeviceOrientationLandscapeRight)
{
//Do Stuff
}
else
{
//Do Stuff
}
So I was going inside my else on FACEUP and FACEDown event which was wrong !
if(orientation == UIDeviceOrientationLandscapeLeft || orientation == UIDeviceOrientationLandscapeRight)
{
//Do Stuff
}
else if(orientation == UIDeviceOrientationPortrait)
{
//Do Stuff
}