Application rotates incorrectly as of iOS 8.3 - ios

I updated to iOS 8.3 and suddenly the Simulator I'm using to debug my XCode/GLES app (iPad 2) is having trouble responding to mouse clicks in the rightmost portion of the screen.
Our application's delegate class name points it to our AppDelegate which derives from UIViewController. Inside the AppDelegate's applicationDidFinishLaunching we then start creating windows - the top-level window being a UIWindow with its main child being a GLView. The application runs in landscape orientation.
Some (possibly important) pieces of code:
Info.plist:
Supported interface orientations
Item 0: Landscape (right home button)
int main(int argc, char *argv[]) // In main.m
{
int retVal = UIApplicationMain(argc, argv, nil, NSStringFromClass([MyAppDelegate class]));
}
#interface MyAppDelegate : UIViewController<UIApplicationDelegate>
{
...
}
#implementation MyAppDelegate
- (void)applicationDidFinishLaunching:(UIApplication *)application
{
[[UIApplication sharedApplication] setStatusBarHidden:YES]];
[[UIApplication sharedApplication].statusBarOrientation = UIInterfaceOrientationLandscapeRight;
CGRect boundingRectangle = CGRectMake(0, 0, 768, 1024);
uIWindow = [[UiWindow alloc] initWithFrame:boundingRectangle];
uIWindow.rootViewController = self; // <-- Added this
[uIWindow setTransform:CGAffineTransformMakeRotation(DegreesToRadians(-90))]; // <-- Added this
boundingRectangle = CGRectMake(0, 260.0, 800, 480);
glViewWindow = [[GLView alloc] initWithFrame:boundingRectangle];
[uiWindow addSubView:glViewWindow];
[uiWindow makeKeyAndVisible];
}
#end
From other stack overflow discussions, it appears the problem is related to the warning we always get "Application windows are expected to have a root view controller at the end of application launch". So we added the line " uIWindow.rootViewController = self;".
This causes the application to be rotated 90 degrees. The simulator is correctly in landscape mode, but the application is in portrait. So we added the "setTransform" line seen above. That rotated the window into the right orientation, but (1) it's offset down and to the left, and (2) none of the mouse clicks work at all anymore (completely unresponsive).
Any ideas on what might be happening here? What can we try next?

Related

How to change home screen for Jailbreak Device programming

I'm a newbie in iOSOpenDev. I want to change the home screen on my jailbroken device. I use iOSOpenDev with Logos tweak to implement this
%hook SBUIController
- (void)finishLaunching
{
SBUIController *uicontroller = (SBUIController *)[%c(SBUIController) sharedInstance];
// Get _contentView & _iconsView from SBUIController
UIView* _contentView = [uicontroller valueForKey:#"_contentView"];
UIView* _iconsView = [uicontroller valueForKey:#"_iconsView"];
// Hidden _iconsView
_iconsView.hidden = YES;
// Add Sphere View
SphereViewManager *sphere = [[SphereViewManager alloc] initWithFrame:[UIScreen mainScreen].bounds];
sphere.frame = [UIScreen mainScreen].bounds;
sphere.tag = 20141201;
[_contentView addSubview:sphere];
}
After SpringBoard is restarted, my home screen is loaded. But when I tap an app to launch, and then I press the HOME button, my device returns to the old home screen. How do I prevent my HOME screen from returning the the old view?

Cordova/PhoneGap iOS: WebView becoming shorter after taking a picture or opening InAppBrowser

When I take a picture with Camera plugin, the whole WebView becomes shorter. It's like the screen is being eaten from bottom for the height of the status bar - 20px. It doesn't have to do with taking a picture at all, it also happens if I only open gallery and then close it. The same thing happens if I open InAppBrowser and then close it. Here is an example:
This is how it looks before choosing a photo
Then the photo choosing dialog appears (doesn't matter if it's emulator, it behaves the same on the real device)
And then this happens when I close the dialog - look at the bottom of the screen
And if I continue to add photos, each time the screen gets 'eaten' by 20px
I found out that the window.innerHeight is getting reduced by 20px, so it has something to do with the status bar. How can I fix this?
I stumbled upon the answer in another thread. Here it is:
In MainViewController.h:
#interface MainViewController : CDVViewController
#property (atomic) BOOL viewSizeChanged;
#end
In MainViewController.m:
#implementation MainViewController
#synthesize viewSizeChanged;
[...]
- (id)init
{
self = [super init];
if (self) {
// On init, size has not yet been changed
self.viewSizeChanged = NO;
// Uncomment to override the CDVCommandDelegateImpl used
// _commandDelegate = [[MainCommandDelegate alloc] initWithViewController:self];
// Uncomment to override the CDVCommandQueue used
// _commandQueue = [[MainCommandQueue alloc] initWithViewController:self];
}
return self;
}
[...]
- (void)viewWillAppear:(BOOL)animated
{
// View defaults to full size. If you want to customize the view's size, or its subviews (e.g. webView),
// you can do so here.
// Lower screen 20px on ios 7 if not already done
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7 && !self.viewSizeChanged) {
CGRect viewBounds = [self.webView bounds];
viewBounds.origin.y = 20;
viewBounds.size.height = viewBounds.size.height - 20;
self.webView.frame = viewBounds;
self.viewSizeChanged = YES;
}
[super viewWillAppear:animated];
}
Source: https://stackoverflow.com/a/19407903/1555838

Single NIB for iPhone and iPad

I see similar questions already here and Google but none answer my actual question. I'd like to have a single NIB for both iPhone and iPad. The NIB itself is supposed to have an empty view only. Everything that should go into the view is done programmatically. I check if device is iPhone/iPad and then calculate and set the layout. A little more work but for the required task this the best solution for me.
But when adding a new view through "New File... -> User Interface -> View" I'm asked for the device Family. The choices are of course iPhone OR iPad. But I want the view to work on both devices, kind of generic.
I tried the iPhone view and it actually works on both devices, iPhone AND iPad. So it seems that everything is fine. My question is more generic asking if it is ok to re-use the iPhone view also for iPad. Shall I do it differently? Any better solution?
Please understand that I really want to work with a single view and programmatically, so solutions to use separate views for each device and use IB shall be left out please!!!
Thanks
If you are creating everything programmatically, there is no need for a nib at all to create an empty view.
Your UIViewController subclass should look like this
#implementation MyViewController
-(void)loadView
{
//Do not call [super loadView] in your implementation.
//The super implementation loads the nib based on the nibName and nibBundle properties.
UIView * view = [[UIView alloc] init];
//Add subviews, etc
//You must assign a UIView object to the view property before loadView completes
self.view = view;
}
#end
You can instantiate the view controller using any format below:
MyViewController * controller = [[MyViewController alloc] initWithNibName:nil bundle:nil];
MyViewController * controller = [[MyViewController alloc] init];
MyViewController * controller = [MyViewController new];
First of all you can do this thing With AutoResize > LINK
and if it become complex for you then you can use below function and do it yourself programmatically.
-(int)setScreenOf
{
int size=0;
if((UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad))
{
//ipad
size=3;
}
else
{
CGRect screenBounds = [[UIScreen mainScreen] bounds];
if (screenBounds.size.height ==568)
{
size=2;
// code for 4-inch screen
}
else
{
size=1;
// code for 3.5-inch screen
}
}
return size;
}
OR if you want to do a Device version Specific code then try this.
-(NSString *)deviceVersion
{
size_t size;
sysctlbyname("hw.machine", NULL, &size, NULL, 0);
char *answer = (char*)malloc(size);
sysctlbyname("hw.machine", answer, &size, NULL, 0);
NSString *platform = [NSString stringWithCString:answer encoding: NSUTF8StringEncoding];
free(answer);
NSLog(#"Platform: %#", platform);
return platform;
}

Rotation behaving differently on iOS6

I did an App which is tab-based. Nothing needs to be on landscape mode but a couple of views. It worked OK on iOS5 and I was pretty happy with the result. However with iOS6 and without messing with anything, it now rotates all the views and the consequences are not nice.
Because its a tab-based app, the couple of view I need in landscape are modalViews. That way I didn't mess with the tabbar and I had only to chose portrait in the "Supported Orientations" setting on build options and set:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return (interfaceOrientation == UIInterfaceOrientationLandscapeLeft);
return (interfaceOrientation == UIInterfaceOrientationLandscapeRight);
}
on the views I wanted landscape.
Now with iOS6 this views are also on portrait mode, no matter what and they do not show the landscape mode even if I rotate the device. Likewise, if I allow all the orientations on the "Supported orientations", they all rotate, no matter what I put on the method above.
On all the views I haven't check the box "Use Autolayout" on storyboards.
Any help here?
*EDIT**
Now that I see it, the App I have on the device works fine. I've installed with a promo code, not from Xcode, only to see whether my customers are having problems or not. Fortunatelly they are not. The problem remains though.
The most important part of the documentation I found for this issue is:
When the user changes the device orientation, the system calls this
method on the root view controller or the topmost presented view
controller that fills the window
To make my app fully working for autorotation in iOS 6, I had to do the following:
1) I created a new subclass of UINavigationController, and added shouldAutorotate and supportedInterfaceOrientation methods:
// MyNavigationController.h:
#import <UIKit/UIKit.h>
#interface MyNavigationController : UINavigationController
#end
// MyNavigationController.m:
#import "MyNavigationController.h"
#implementation MyNavigationController
...
- (BOOL)shouldAutorotate {
return YES;
}
- (NSUInteger)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskAll;
}
...
#end
2) In the AppDelegate, I did use my new subclass to show my root ViewController (it is introScreenViewController, a UIViewController subclass) and did set the self.window.rootViewController, so it looks that:
nvc = [[MyNavigationController alloc] initWithRootViewController:introScreenViewController];
nvc.navigationBarHidden = YES;
self.window.rootViewController = nvc;
[window addSubview:nvc.view];
[window makeKeyAndVisible];
This is the alternative solution for iOS6 in case you are using the tab bar controller. It also shows that is NOT needed to override UINavigationController or even UITabBarController.
In your xyzAppDelegate.h add this interface:
#interface UITabBarController (MyApp)
#end
And in xyzAppDelegate.m add these methods:
#implementation UITabBarController (MyApp)
-(BOOL)shouldAutorotate
{
return YES;
}
- (NSUInteger)supportedInterfaceOrientations
{
// your custom logic for rotation of selected tab
if (self.selectedIndex==...) {
return UIInterfaceOrientationMaskAll;
}
else {
return UIInterfaceOrientationMaskPortrait|UIInterfaceOrientationMaskPortraitUpsideDown;
}
}
#end
Also, set the root view controller for the app window:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
...
[self.window setRootViewController:tabBarController];
Are you setting the rootViewController in the delegate? For example,
self.window.rootViewController = self.navigationController;
When I was doing some iOS6 testing it wouldn't work properly until I did that...
I have a good solution for cross 5.0 to 6.0 working - All of the above with
-(BOOL)shouldAutorotate{return [self shouldIRotateAnyiOS];}//iOS6
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation{return [self shouldIRotateAnyiOS];}//pre iOS6
-(BOOL)shouldIRotateAnyiOS{
UIInterfaceOrientation interfaceOrientation = [[UIDevice currentDevice] orientation];
//do the rotation stuff
return YES
}
You might double check Support Interface Orientations
On previous version, it means nothing, but affects whole application now.
Note: The 'upside down' option doesn't work even enabled or disabled on iOS 6.
This is what works for me.
I created a new subclass of UINavigationController, and added shouldAutorotate and supportedInterfaceOrientation methods:
#import "MyNavigationController.h"
#interface MyNavigationController ()
#end
#implementation MyNavigationController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (BOOL)shouldAutorotate {
return [self.visibleViewController shouldAutorotate];
}
- (NSUInteger)supportedInterfaceOrientations {
return [self.visibleViewController supportedInterfaceOrientations];
}
#end
Then add this to your delegate
UINavigationController *nvc = [[MyNavigationController alloc] initWithRootViewController:_viewController];
nvc.navigationBarHidden = NO; // YES if you want to hide the navigationBar
self.window.rootViewController = nvc;
[_window addSubview:nvc.view];
[_window makeKeyAndVisible];
Now you can add this to the views you want to rotate in all orientations
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return YES;
}
-(NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskAll;
}
-(BOOL)shouldAutorotate
{
return YES;
}
Or add this to the views you only want to go portrait and portraitUpsideDown
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return
(interfaceOrientation == UIInterfaceOrientationPortrait || interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown);
}
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskPortraitUpsideDown ;
}
- (BOOL)shouldAutorotate
{
return YES;
}
There are a few things you may need to handle to get this working since with iOS6 the structure of autorotate has changed. The structure of how autorotate is determined is now reversed. It used to be that an individual view controller can control the autorotate with its decision but now the "shouldAutorotate" is determined by the highest parent in the navigation which in your case is the tabBar.
You need to make sure your window has a rootViewController set and not just added as a subview.
You may need to subclass your tabBarController to implement both "supportedInterfaceOrientations" and "shouldAutorotate".
If there are any viewControllers that need to behave differently then you will need to have your tabBarController consult with them for the answer on whether they should autorotate.
for example:
- (BOOL)shouldAutorotate
{
return self.selectedViewController.shouldAutorotate;
}
and in your view controller you would implement shouldAutorotate and make the decision there.
From Apple's documentation for shouldAutorotateToInterfaceOrientation:
Override the supportedInterfaceOrientations and preferredInterfaceOrientationForPresentation methods instead.
http://developer.apple.com/library/ios/#documentation/uikit/reference/UIViewController_Class/DeprecationAppendix/AppendixADeprecatedAPI.html#//apple_ref/occ/instm/UIViewController/shouldAutorotateToInterfaceOrientation:
For app "Same Picture" on iOS6 I need an orientation change, my UIViewController never be informed for orientation, it's an photo overlay likely didrotate works well :
- (void)didRotate: ( NSNotification* )note
{
[self performSelector:#selector(rotateRecalculDiffere) withObject:nil afterDelay:0.3 ];
}
I make fine size adjust with delayed call. From notification it's easy to know final orientation
Did a little experimentation: Took an existing app (that wouldn't rotate in iOS-6, but did previously) and added the one line self.window.rootViewController = navCtlr; to AppDelegate. This resulted in an app that appears (at least at first blush) to rotate just fine.
Then, out of curiosity, I created the RotationCanary class and plugged an instance of that into self.window.rootViewController. I'd start up the app and wait for the inevitable "unrecognized selector", create a new method of that name in RotationCanary, and re-run. The new method would call the real nav ctlr and log its response before returning it. This produced (sooner than I expected) the following log:
2012-12-07 13:08:47.689 MyTestApp[53328:c07] System Version is 6.0; Supported versions are 5.0.x to 6.0.x
2012-12-07 13:08:47.691 MyTestApp[53328:c07] Host memory (in bytes) used: 3489513472 free: 803893248 total: 4293406720
2012-12-07 13:08:47.692 MyTestApp[53328:c07] Memory in use by task (in bytes): 23719936
2012-12-07 13:08:47.695 MyTestApp[53328:c07] Creating database
2012-12-07 13:08:47.699 MyTestApp[53328:c07] Item Selected: (null) (null)
2012-12-07 13:08:47.700 MyTestApp[53328:c07] <DetailViewController.m:(27)> Entering Method -[DetailViewController viewDidLoad]
2012-12-07 13:08:47.706 MyTestApp[53328:c07] <SplitContentViewController.m:(57)> Entering Method -[SplitContentViewController viewDidLoad]
2012-12-07 13:08:47.708 MyTestApp[53328:c07] <FamilyMasterViewController.m:(32)> Entering Method -[FamilyMasterViewController viewDidLoad]
2012-12-07 13:08:47.709 MyTestApp[53328:c07] <MasterViewController.m:(41)> Entering Method -[MasterViewController viewDidLoad]
2012-12-07 13:08:47.718 MyTestApp[53328:c07] <FamilyHomeDetailViewController.m:(51)> Entering Method -[FamilyHomeDetailViewController viewDidLoad]
2012-12-07 13:08:47.820 MyTestApp[53328:c07] -[RotationCanary _preferredInterfaceOrientationGivenCurrentOrientation:] - current = 2, result = 2
2012-12-07 13:08:47.821 MyTestApp[53328:c07] -[RotationCanary _existingView] - view = (null)
2012-12-07 13:08:47.824 MyTestApp[53328:c07] -[RotationCanary view] - view = <UILayoutContainerView: 0x9c987f0; frame = (0 0; 768 1024); autoresize = W+H; layer = <CALayer: 0x9c8fa00>>
2012-12-07 13:08:47.825 MyTestApp[53328:c07] -[RotationCanary view] - view = <UILayoutContainerView: 0x9c987f0; frame = (0 0; 768 1024); autoresize = W+H; layer = <CALayer: 0x9c8fa00>>
2012-12-07 13:08:47.826 MyTestApp[53328:c07] -[RotationCanary view] - view = <UILayoutContainerView: 0x9c987f0; frame = (0 0; 768 1024); autoresize = W+H; layer = <CALayer: 0x9c8fa00>>
2012-12-07 13:08:47.827 MyTestApp[53328:c07] -[RotationCanary wantsFullScreenLayout] - result = YES
2012-12-07 13:08:47.827 MyTestApp[53328:c07] -[RotationCanary view] - view = <UILayoutContainerView: 0x9c987f0; frame = (0 0; 768 1024); autoresize = W+H; layer = <CALayer: 0x9c8fa00>>
2012-12-07 13:08:47.830 MyTestApp[53328:c07] -[RotationCanary _tryBecomeRootViewControllerInWindow:] - window = <UIWindow: 0x9c76320; frame = (0 0; 768 1024); opaque = NO; autoresize = RM+BM; layer = <UIWindowLayer: 0x9c76450>>, result = YES
2012-12-07 13:08:47.916 MyTestApp[53328:c07] -[RotationCanary _deepestDefaultFirstResponder] - result = <SignOnViewController: 0x9c942a0>
2012-12-07 13:08:47.916 MyTestApp[53328:c07] Device model: x86_64
Curiously, the class was never actually invoked to perform rotation -- only during setup.
I suspect that Apple uses the setting of rootViewController purely as a way to indicate that the app has been modified for iOS 6 rotation -- it has no real function otherwise.
FWIW: It occurred to me that the caller might be using respondsToSelector and skipping some calls, so I added an implementation of resolveInstanceMethod: to RotationCanary, to trap any such attempts. None occurred.
Autorotation changed in iOS 6.0. Check this link for more information.
Autorotation is changing in iOS 6. In iOS 6, the shouldAutorotateToInterfaceOrientation:
method of UIViewController is deprecated. In its place, you should use the
supportedInterfaceOrientations and shouldAutorotate methods.
This code common for ios5 and ios6
-(void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation duration:(NSTimeInterval)duration {
if (UIInterfaceOrientationIsLandscape(interfaceOrientation)) {
[self performSelector:#selector(setframeLandscap) withObject:nil afterDelay:0.2];
}
else {
[self performSelector:#selector(setframePortrait) withObject:nil afterDelay:0.2];
}
}
-(BOOL)shouldAutorotate {
return YES;
}

Open Game Center UI with Cocos2d-x

I have set up so that my app can connect to the Game Center. I followed this guide and had a C++ class wrapper to call them in my other classes. I'm using iPad (iOS 5.1), iPod Touch 4th Gen (iOS 5.1), and iPhone 4s and 3GS to test. It works fine on iPad devices but for some unknown reason, it does not on iPhone and iPod. It properly connects to the Sandbox but the UI is not shown, or rather, the UI is somewhere off-screen.
What happens on the iPhone is:
If I'm not logged in and I access the Game Center, a login window appears. When I log in, nothing happens. However, the console says a view is added.
If I'm logged in and I access the Game Center, nothing happens. However, the console says a view is added.
If I access the Game Center before I get authenticated, the Game Center UI appears. However...
The Game Center is in Landscape Mode (no problem there, since my app is in landscape) but the top bar (the bar with the DONE button) is placed as if the orientation is portrait.
The whole UI is not shown, just ~30% of the screen.
This is how I launch the Game Center UI:
- (void)showLeaderboardForCategory:(NSString *)category
{
// Only execute if OS supports Game Center & player is logged in
if ( hasGameCenter )
{
// Create leaderboard view w/ default Game Center style
GKLeaderboardViewController *leaderboardController = [[GKLeaderboardViewController alloc] init];
// If view controller was successfully created...
if (leaderboardController != nil)
{
// Leaderboard config
leaderboardController.leaderboardDelegate = self; // The leaderboard view controller will send messages to this object
leaderboardController.category = category; // Set category here
leaderboardController.timeScope = GKLeaderboardTimeScopeToday; // GKLeaderboardTimeScopeToday, GKLeaderboardTimeScopeWeek, GKLeaderboardTimeScopeAllTime
// Create an additional UIViewController to attach the GKLeaderboardViewController to
myViewController = [[UIViewController alloc] initWithNibName:nil bundle:nil ];
// Add the temporary UIViewController to the main OpenGL view
// NOTE: This is the part that I think is the suspect. I am not sure if iPhones and iPods support EAGLView.
[ [ EAGLView sharedEGLView ] addSubview:myViewController.view ];
// Tell UIViewController to present the leaderboard
[ myViewController presentModalViewController:leaderboardController animated:NO ];
NSLog( #"Leaderboard opened." );
}
}
}
Any help is appreciated and thanks in advance.
EDIT: Using OpenFeint is not an option.
Try this.Do not use 'EAGLView'
- (void) showLeaderboard
{
if (!gameCenterAvailable) return;
GKLeaderboardViewController *leaderboardController = [[GKLeaderboardViewController alloc] init];
if (leaderboardController != nil) {
leaderboardController.leaderboardDelegate = self;
UIWindow *window = [[UIApplication sharedApplication] keyWindow];
currentModalViewController = [[UIViewController alloc] init];
[window addSubview:currentModalViewController.view];
[currentModalViewController presentModalViewController:leaderboardController animated:YES];
}
}

Resources