When updating my app to iOS6 standard the portrait / landscape is gone. Ir worked perfectly when I was building with Xcode 3. But now using latest Xcode and latest SDK the rotation is gone and it is always in portrait mode. No matter what I put in "Supported interface Orientations". And the code I used to get rotation before seems to have no effect at all.
I had these lines.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
{
switch (toInterfaceOrientation) {
case UIInterfaceOrientationPortrait:
case UIInterfaceOrientationLandscapeLeft:
case UIInterfaceOrientationLandscapeRight:
return YES;
default:
return NO;
}
}
How do I change and what do I change to get it work again?
First of all, in AppDelegate, write this. THIS IS VERY IMP
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
return (UIInterfaceOrientationMaskAll);
}
Then, For UIViewControllers, in which you need only PORTRAIT mode, write these functions
- (BOOL)shouldAutorotate
{
return YES;
}
- (NSUInteger)supportedInterfaceOrientations
{
return (UIInterfaceOrientationMaskPortrait);
}
For UIViewControllers, which require LANDSCAPE too, change masking to All.
- (NSUInteger)supportedInterfaceOrientations
{
return (UIInterfaceOrientationMaskAllButUpsideDown);
//OR return (UIInterfaceOrientationMaskAll);
}
Now, if you want to do some changes when Orientation changes, then use this function.
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
}
EDIT :
A lot depends on with which controller is your UIViewController embedded in.
Eg, If its inside UINavigationController, then you might need to subclass that UINavigationController to override orientation methods like this.
subclassed UINavigationController (the top viewcontroller of the hierarchy will take control of the orientation.) did set it as self.window.rootViewController.
- (BOOL)shouldAutorotate
{
return self.topViewController.shouldAutorotate;
}
- (NSUInteger)supportedInterfaceOrientations
{
return self.topViewController.supportedInterfaceOrientations;
}
From iOS 6, it is given that UINavigationController won't ask its UIVIewControllers for orientation support. Hence we would need to subclass it.
How to support one or more landscape controllers in app that is portrait mainly in ios6:
1) in AppDelegate
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
UINavigationController* ns = (UINavigationController*)self.window.rootViewController;
if (ns) {
UIViewController* vc = [ns visibleViewController];
//by this UIViewController that needs landscape is identified
if ([vc respondsToSelector:#selector(needIos6Landscape)])
return [vc supportedInterfaceOrientations];
}
return UIInterfaceOrientationMaskPortrait; //return default value
}
2) in UIView controller(s) that needs landscape (or portrait+lanscape etc):
//flag method
-(void)needIos6Landscape {
}
- (BOOL)shouldAutorotate
{
return YES;
}
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskAllButUpsideDown;
}
3) in controllers, to which you can RETURN from controllers, that can be rotated in landscape - this is important, otherwise they remaind landscape on return from landscape-enabled VC.
- (BOOL)shouldAutorotate
{
return YES;
}
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskPortrait;
}
4) (maybe not needed, but for sure..) - subclass navigation controller(s) you using, and add:
- (BOOL)shouldAutorotate
{
return YES;
}
- (NSUInteger)supportedInterfaceOrientations
{
UIViewController* vc = [self visibleViewController];
if (vc) {
if ([vc respondsToSelector:#selector(needIos6Landscape)]) {
return [vc supportedInterfaceOrientations];
}
}
return UIInterfaceOrientationMaskPortrait;
}
The important step is to ask for orientation only controllers from your app, because during transition between controllers, for some time there is some system controller as root, and will return incorrect value (this took me 2 hrs to find out, it was reason it was not working).
Don't know whether your issue was alike but with me, the status bar was oriented correctly (landscape) and the UIViewController was portrayed.
I changed following line in the application delegate application:didFinishLaunchingWithOptions:
//[window addSubview:navigationController.view];
self.window.rootViewController = navigationController;
Apple=> this costed me a day and a half to find out, and a lot of money!!!
Related
I have an NSWindow that has a drop shadow, but it is way to dark. The shadow spreads too far and is too heavy for me. It's the default shadow for the NSWindow and I haven't edited it at all.
What I want to know is if there is a way to shorten the blur radius or lower the heaviness of the drop shadow so it appears a bit more subtle.
Thanks!
There's no public API, but you can do It by swizzling some methods on NSThemeFrame (this is the view class responsible for the window's frame, border, etc).
Here's an example ( a subclass of NSWindow):
#import <objc/runtime.h>
#interface SOWindow : NSWindow
#end
#interface SOWindowThemeFrameOverrides : NSView
#end
#implementation SOWindow
+ (void)load
{
NSArray *methodsToOverride = #[#"_shadowOffset", #"_shadowFlags", #"_shadowType"];
for (NSString *selector in methodsToOverride) {
Method m = class_getInstanceMethod(NSClassFromString(#"NSThemeFrame"), NSSelectorFromString(selector));
Method m2 = class_getInstanceMethod([SOWindowThemeFrameOverrides class], NSSelectorFromString(selector));
class_addMethod(NSClassFromString(#"NSThemeFrame"), NSSelectorFromString([NSString stringWithFormat:#"_original%#", selector]), method_getImplementation(m), method_getTypeEncoding(m));
method_exchangeImplementations(m, m2);
}
}
#end
#implementation SOWindowThemeFrameOverrides
- (NSSize)_shadowOffset
{
if ([self.window isKindOfClass:[SOWindow class]]) {
return NSMakeSize(0, 8);
} else {
return [self _original_shadowOffset];
}
}
- (NSUInteger)_shadowFlags
{
if ([self.window isKindOfClass:[SOWindow class]]) {
return 0;
} else {
return [self _original_shadowFlags];
}
}
- (NSInteger)_shadowType
{
if ([self.window isKindOfClass:[SOWindow class]]) {
return 4;
} else {
return [self _original_shadowType];
}
}
#pragma mark Placeholder methods
- (NSSize)_original_shadowOffset
{
// implementation will be filled in at runtime
return NSZeroSize;
}
- (NSUInteger)_original_shadowFlags
{
// implementation will be filled in at runtime
return 0;
}
- (NSInteger)_original_shadowType
{
// implementation will be filled in at runtime
return 0;
}
#end
When the SOWindow class is loaded by the runtime, the + load method is invoked. The method switches NSThemeFrame's implementation of the 3 shadow methods by their implementation in SOWindowThemeFrameOverrides, also adding the original methods to the class with the _original prefix.
When the swizzled methods are called, we check to see if the window is a SOWindow, if It is we use the custom shadow, if It's not we forward the call to the original implementations.
This is what I get by returning 4 from _shadowType:
Please note that this is a huge hack and would probably be rejected if you tried to submit It to the AppStore.
I am using Xcode and after updating to iOS 8, the shouldAutorotate function doesn't work.
I don't want my viewcontroller to autorotate.
How can I restrict autorotation in iOS 8 from Xcode?
Follow these steps:
First, in info.plist select the orientations which your application supports. Meaning if your application only displays in portrait mode then select portrait as your only setting.
If you want to restrict this orientation from appdelegate you can add this code
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {
NSUInteger orientations;
UIViewController* presented = [[[[NavigationManager sharedManager ] navigationController] viewControllers] lastObject];
orientations = [presented supportedInterfaceOrientations];
return orientations;
}
Make common class for UIViewcontroller and add these methods:
BaseViewController.h
#interface BaseViewController : UIViewController{
}
BaseViewController.m
- (BOOL)shouldAutorotate
{
return NO;
}
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskPortrait;
}
Add the following code in Navigation controller class
-(BOOL)shouldAutorotate
{
return NO;
}
-(NSUInteger)supportedInterfaceOrientation
{
return UIInterfaceOrientationPortrait;
}
Does anybody knows how to get the UITextField from any UISearchBar on iOS 7.1, i need to change the font and search icon but the old code doesn´t work with the new version 7.1, Thanks for your help.
This is the old code to get the UITextField, this only works on versions less than 7.1
UITextField *txfSearchField = [default_search_bar valueForKeyPath:#"_searchField"];
If you are in subclass of UISearchBar you can use simple fix.
Somehow after init there are not instances of UITextField in subviews.
But in - (void)layoutSubviews you can find it.
So the solution is to move code, that search for textfield out of init.
You can use this simple method, that will work on all iOS prior to 7.1
- (UIView *)firstViewOfClass:(Class)class inSubviewsOfView:(UIView *)view
{
UIView *result = nil;
for (UIView *subview in view.subviews)
{
if ([subview isKindOfClass:class])
{
result = subview;
}
else
{
result = [self firstViewOfClass:class inSubviewsOfView:subview];
}
if (result)
{
break;
}
}
return result;
}
Example of usage:
- (void)layoutSubviews
{
if (!self.textField)
{
self.textField = (UITextField *)[self firstViewOfClass:[UITextField class] inSubviewsOfView:self];
}
[super layoutSubviews];
// your code here.
}
You should try to search for it like this:
for (UIView* subView in self.searchBar.subviews) {
for (UIView* searchView in subView.subviews) {
if ([searchView isKindOfClass:[UITextField class]]) {
self.searchTextField = (UITextField*)searchView;
break;
}
}
}
just updated to IOS SDK 6 and now I'm confused. Tried to find a solution but I failed.
Created a new "Single View iPad APP" (I have an iPad 3) in xcode
Disabled Portrait & Upside-Down interface orientations in TARGETS->Summary
Set simulated metrics "orientation" to "Landscape"
Added following lines of code into the view controller file:
- (BOOL)shouldAutorotate {
return YES;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
return UIInterfaceOrientationLandscapeLeft | UIInterfaceOrientationLandscapeRight;
}
- (NSUInteger)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskLandscape;
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
NSLog(#"%#", NSStringFromCGRect(self.view.frame));
}
Run APP
My output is: 2012-10-09 18:18:40.149 TestApp[6165:907] {{20, 0}, {748, 1024}}
Does anybody know why the frame is not ... {{0, 20}, {1024, 748}} as I would expect? Maybe I missed something!
Thank you!
I don't think you missed anything, but if you wrap your view controller with a UINavigationController, the frame will be set as expected.
NB: With the iOS 6 SDK, you can no longer combine any of the UIInterfaceOrientation constants as a mask. So you need:
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
return UIInterfaceOrientationLandscapeLeft;
}
That doesn't explain the issue, though, since preferredInterfaceOrientationForPresentation is not called when a view controller is the root controller of a UIWindow.
I have an app with a cuople of views with different view controllers. One is a map view and one a web view that I want to be available both in portrait/landscape. Before I just this code that in all my view controllers that locked all of them in portrait:
- (BOOL)shouldAutorotateToInterfaceOrientation: (UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
But when I updated to Xcode 4.5/IOS6 all of them suddenly could be flipped. So now I decided to keep the map view/web view flippable. But I have a menu that I want to be locked in portrait and I doesn't work with the code above nor with:
}
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return NO;
}
Any ideas?
Thanks on beforehand!
You could just do it from the project settings in Project -> Targets -> Project Name -> Summary -> Supported Interface Orientations -> Portrait.
Alternatively, you could add the following to your appdelegate -
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window{
return UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskPortraitUpsideDown;
}
And add the following to your viewcontroller -
- (NSUInteger)supportedInterfaceOrientations
{
// UIInterfaceOrientationMaskLandscape;
// 24
//
// UIInterfaceOrientationMaskLandscapeLeft;
// 16
//
// UIInterfaceOrientationMaskLandscapeRight;
// 8
//
// UIInterfaceOrientationMaskPortrait;
// 2
// return UIInterfaceOrientationMaskPortrait;
// or
return UIInterfaceOrientationMaskPortrait;
}
-(BOOL) shouldAutorotate
{
return YES;
}