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;
}
Related
I've been searching high and low for an example of an easy implementation of Quicklook to an existing NSTableView and while I've found example projects they're way beyond my skill set to disassemble and duct-tape into my project.
I can get the Quicklook window to appear when a button is pressed using
[[QLPreviewPanel sharedPreviewPanel] makeKeyAndOrderFront:nil];
But I haven't the slightest clue on how to set the data source so that the window is populated with the file.
Simply put, is there any stupid-simple tutorial on how to do this...?
Create a class that conforms to the QLPreviewItem protocol and implement:
- (NSURL *)previewItemURL {
// <Return File URL for file you want to preview>
}
Have your class that triggers the preview panel implement QLPreviewPanelDataSource, QLPreviewPanelDelegate and add the following to your implementation:
# pragma mark - QuartzPanel
- (IBAction)togglePreviewPanel:(id)previewPanel {
if ([QLPreviewPanel sharedPreviewPanelExists] && [[QLPreviewPanel sharedPreviewPanel] isVisible]) {
[[QLPreviewPanel sharedPreviewPanel] orderOut:nil];
} else {
[[QLPreviewPanel sharedPreviewPanel] makeKeyAndOrderFront:nil];
}
}
- (BOOL)acceptsFirstResponder {
return YES;
}
- (BOOL)acceptsPreviewPanelControl:(QLPreviewPanel *)panel {
return YES;
}
- (void)beginPreviewPanelControl:(QLPreviewPanel *)panel {
_previewPanel = panel; // create a property to hold a reference to your panel
panel.delegate = self;
panel.dataSource = self;
}
- (void)endPreviewPanelControl:(QLPreviewPanel *)panel {
_previewPanel = nil;
}
#pragma mark - QLPreviewPanelDataSource
- (NSInteger)numberOfPreviewItemsInPreviewPanel:(QLPreviewPanel *)panel {
return self.previewItems.count; // Items to preview of your custom subclass you created above
}
- (id <QLPreviewItem>)previewPanel:(QLPreviewPanel *)panel previewItemAtIndex:(NSInteger)index {
return (id<QLPreviewItem>)self.previewItems[index];
}
#pragma mark - QLPreviewPanelDelegate
- (BOOL)previewPanel:(QLPreviewPanel *)panel handleEvent:(NSEvent *)event {
// redirect all key down events to the table view
if ([event type] == NSKeyDown) {
NSString *key = [event charactersIgnoringModifiers];
if ([key isEqual:#" "]) {
[self togglePreviewPanel:self];
}
return YES;
}
return NO;
}
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;
}
}
}
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!!!
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;
}
I've made an application where you shake the phone to open a new view. All together three views, and when you shake the phone on the last view you go back to the first screen. This works fine when I'm creating new subclass controls view with their own .xib. But I would like to use this in a storyboard project, what do I need to change?
Thanks a lot on beforehand!
HERE IS THE CODE IN .H:
#import <UIKit/UIKit.h>
#import "FirstScreenViewController.h"
#import "SecondScreenViewController.h"
#interface ViewController : UIViewController
{
NSInteger currentScreen;
UIViewController* currentController;
}
#end
AND HERE IN THE .M:
#import "ViewController.h"
#implementation ViewController
-(void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
#pragma mark shake
-(BOOL)canBecomeFirstResponder
{
return true;
}
-(void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event
{
if(motion == UIEventSubtypeMotionShake)
{
if (currentController)
{
[currentController.view removeFromSuperview];
currentController=nil;
}
switch (currentScreen)
{
case 0:
currentController = [[FirstScreenViewController alloc] initWithNibName:#"FirstScreenViewController" bundle:nil];
break;
case 1:
currentController = [[SecondScreenViewController alloc] initWithNibName:#"SecondScreenViewController" bundle:nil];
}
if(currentController)
{
[currentController.view setFrame:self.view.bounds];
[self.view addSubview:currentController.view];
}
currentScreen++;
if(currentScreen >2)
currentScreen=0;
}
}
#pragma mark - View lifecycle
-(void)viewDidLoad
{
[super viewDidLoad];
currentScreen = 0;
}
-(void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
#end
You need to add all three view controllers to the storyboard, and have segues between them (including one back to the first from the third) and a shake gesture recogniser attached to each scene.
The action method for each gesture recogniser tells the view controller to performSegue: with the appropriate segue identifier.