iOS 7: Restrict device current orientation when modal view controller is presented - cocoa

I have a UIViewController which contains a UICollectionView. On tapping any of the UICollectionViewCell I present a modal view controller.
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
PopViewController *vc = [storyboard instantiateViewControllerWithIdentifier:#"DetailsView"];
vc.view.backgroundColor = [UIColor clearColor];
vc.transitioningDelegate = self;
vc.modalPresentationStyle = UIModalPresentationCustom;
[self presentViewController:vc animated:YES completion:nil];
The PopViewController shows up correctly. Now I want to restrict the device orientation when PopViewController is being presented. That is if PopViewController is presented in portrait mode then it should not change to landscape even if I switch to landscape mode (using Rotate Left or Right in simulator) until I dismiss the PopViewController.
I have used following code in PopViewController:
-(BOOL)shouldAutorotate {
return NO;
}
What else (or instead) is needed to lock the pop up view to the current orientation?

in your modal controller try to add this, also (iOS > 6)
-(NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskPortrait;
}
to support iOS 5 or below you must additional add:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
{
return (toInterfaceOrientation == UIInterfaceOrientationPortrait);
}

Related

make modally presentation from UISplitViewControllers primary view to detail view

I have a plus button in my primary view controller of a UISplitViewController and i want to present something modally in my detail view, just like apple does when adding a new contact in address book in iPad. I have tried everything but nothing. I managed to do it but when i am trying to embed my presented view controller into a UINavigation controller then my presented controller covers the full screen. Any suggestions? Here is my code:
UINavigationController *navController = [self.splitViewController.viewControllers lastObject];
DetailTableViewController *controller = (DetailTableViewController *)navController.topViewController;
controller.definesPresentationContext = YES;
controller.providesPresentationContextTransitionStyle = YES;
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
EditTableViewController *etvc = (EditTableViewController *)[storyboard instantiateViewControllerWithIdentifier:#"EditTableViewController"];
UINavigationController *nav = [[UINavigationController alloc]initWithRootViewController:etvc];
etvc.patient = patient;
if (IDIOM == IPAD)
{
etvc.modalPresentationStyle = UIModalPresentationCurrentContext;
[controller presentViewController:nav animated:YES completion:nil];
} else {
[self presentViewController:nav animated:YES completion:nil];
}
I just successfully solved this problem by creating a custom segue whose implementation is:
- (void)perform
{
UIViewController *ctrl = self.sourceViewController;
UIViewController *dest = self.destinationViewController;
dest.modalPresentationStyle = UIModalPresentationCurrentContext;
[ctrl presentViewController:dest animated:YES completion:nil];
}
I'm seeing the behavior I want by invoking this segue from my detail view controller on the modal view I want to overlay it.
I think where your code is going haywire is here:
etvc.modalPresentationStyle = UIModalPresentationCurrentContext;
I think it should be:
nav.modalPresentationStyle = UIModalPresentationCurrentContext;
Though I haven't tested it.
Note that the Apple docs suggest that modalPresentationStyle is ignored on the iPhone (or on "horizontally compact devices"), so your "IS_IPAD" check may be redundant.
Hope this helps!

Presenting UIImagePickerController over modally presented view controller does not work correctly in iOS 8

I have presented UIImagePickerController from modally presented view controller. After clicking the image I get a black image instead of the clicked picture
I did something Like this.
//From ViewController1 I presented view controller2 with
- (IBAction)buttontappedToPresentViewController2:(id)sender
{
ViewController2* controller2 = [[ViewController2 alloc] initWithNibName:#"ViewController2" bundle:nil];
controller2.modalPresentationStyle = UIModalPresentationPageSheet;
[self controller2 animated:YES completion:nil];
}
//In ViewController2, I presented the UIIMagePickerController
- (IBAction)cameraButtonTapped:(id)sender
{
UIImagePickerController *cameraController = [[UIImagePickerController alloc] init];
cameraController.mediaTypes = #[(NSString *)kUTTypeImage,(NSString*)kUTTypeMovie];
cameraController.sourceType = UIImagePickerControllerSourceTypeCamera;
[self presentViewController:cameraController animated:YES completion:NULL];
}
After clicking the image you will get black screen instead of the captured image with retake and use photo options. If you select "Use Photo" option you get the correct image in callback.
Note: If you do not set UIModalPresentationStyle for viewController2, the code works fine.
Any idea what is going wrong here.
EDIT: I have used XCODE 5.1 and my target deployment is iOS 7. I am running the app on iOS8 device.

Chromium Tabs are reseting flash content in WebView

I'm working with https://github.com/rsms/chromium-tabs in my project and I have created my app so the tabs are registered to a WebView. When I'm debugging I noticed that when I was viewing a Youtube video or any flash content and I switched tabs then switch back the content reloaded or the video restarted. Is there any reason this should hapen.
When a tab is selected it is set: [self becomeFirstResponder];
Other than that I have found no other connected way the flash would reset and the rest of the page would remain the same. I'm believing its a setting in WebView whenever it is not visible.
For the comment bellow:
I followed the examples on Github and used MyTabContents.mm to create the contents. Also used a custom webview.
MyTabContents.mm:
-(id)initWithBaseTabContents:(CTTabContents*)baseContents {
if (!(self = [super initWithBaseTabContents:baseContents])) return nil;
ProgressWebView *wv = [[ProgressWebView alloc] initWithFrame:NSZeroRect];
[wv setProgressDelegate:self];
[[wv mainFrame] loadRequest:[[NSURLRequest alloc] initWithURL:[NSURL URLWithString:#"https://google.com"]]];
[wv setShouldUpdateWhileOffscreen:YES];
webView = wv;
// Create a NSScrollView to which we add the NSTextView
NSScrollView *sv = [[NSScrollView alloc] initWithFrame:NSZeroRect];
[sv setDocumentView:wv];
[sv setHasVerticalScroller:NO];
// Set the NSScrollView as our view
self.view = sv;
return self;
}
AppDelegate.mm:
- (void)applicationDidFinishLaunching:(NSNotification *)notification {
CTBrowserWindowController* windowController =
[[CTBrowserWindowController alloc] initWithBrowser:[MyBrowser browser]];
[windowController.browser addBlankTabInForeground:YES];
[windowController showWindow:self];
}
MyBrowser.mm:
-(CTTabContents*)createBlankTabBasedOn:(CTTabContents*)baseContents {
// Create a new instance of our tab type
MyTabContents *contents = [[MyTabContents alloc]
initWithBaseTabContents:baseContents];
[self changeLayout];
return [contents autorelease];
}

xcode iOS6 orientation landscape

I see a lot of questions about this subject but am unable to find a solution to the problem I am experiencing. I have created an iPad app that should be Landscape only - it works fine when ran on any os prior to iOS6 but on iOS6 the app opens in portrait view. This screenshot shows what I mean (sorry not a great explanation) http://s1342.beta.photobucket.com/user/designedbyria/media/ScreenShot2012-11-02at122113.png.html
I'm guessing the problem is somewhere in the below code, but I can't be sure. I have set the supported Interface Orientations to Landscape Left and Landscape Right only - but this has not worked. I have also taken a look at the questions here with no luck..
I am using xcode and cordova/phonegap
Interface orientation in iOS 6.0
Set orientation to landscape mode in xcode 4.5 GM IOS 6
iOS 6 apps - how to deal with iPhone 5 screen size?
Thanks in Advance!
/**
* This is main kick off after the app inits, the views and Settings are setup here. (preferred - iOS4 and up)
/
- (BOOL) application:(UIApplication)application didFinishLaunchingWithOptions: (NSDictionary*)launchOptions {
NSURL* url = [launchOptions objectForKey:UIApplicationLaunchOptionsURLKey];
NSString* invokeString = nil;
if (url && [url isKindOfClass:[NSURL class]]) {
invokeString = [url absoluteString]; NSLog(#"iwill launchOptions = %#", url);
}
CGRect screenBounds = [[UIScreen mainScreen] bounds];
self.window = [[[UIWindow alloc] initWithFrame:screenBounds] autorelease];
self.window.autoresizesSubviews = YES;
CGRect viewBounds = [[UIScreen mainScreen] applicationFrame];
self.viewController = [[[MainViewController alloc] init] autorelease];
self.viewController.useSplashScreen = YES;
self.viewController.wwwFolderName = #"www";
self.viewController.startPage = #"index.html";
self.viewController.invokeString = invokeString;
self.viewController.view.frame = viewBounds;
// check whether the current orientation is supported: if it is, keep it, rather than forcing a rotation
BOOL forceStartupRotation = YES;
UIDeviceOrientation curDevOrientation = [[UIDevice currentDevice] orientation];
if (UIDeviceOrientationUnknown == UIInterfaceOrientationLandscapeLeft) {
// UIDevice isn't firing orientation notifications yet… go look at the status bar
curDevOrientation = (UIDeviceOrientation)[[UIApplication sharedApplication] statusBarOrientation];
}
if (UIDeviceOrientationIsValidInterfaceOrientation(curDevOrientation)) {
for (NSNumber *orient in self.viewController.supportedOrientations) {
if ([orient intValue] == curDevOrientation) {
forceStartupRotation = YES;
break;
}
}
}
if (forceStartupRotation) {
NSLog(#"supportedOrientations: %#", self.viewController.supportedOrientations);
// The first item in the supportedOrientations array is the start orientation (guaranteed to be at least Portrait)
UIInterfaceOrientation newOrient = [[self.viewController.supportedOrientations objectAtIndex:0]
intValue];
NSLog(#"AppDelegate forcing status bar to: %d from: %d", newOrient, curDevOrientation);
[[UIApplication sharedApplication] setStatusBarOrientation:newOrient];
}
[self.window addSubview:self.viewController.view];
[self.window makeKeyAndVisible];
return YES; }
I had the same problem (but not using cordova/phonegap).
You have to set your view controller as a RootViewController in your appDelegate instead of just adding as a subview.
Replace in you appdelegate:
[self.window addSubview:self.viewController.view];
[self.window makeKeyAndVisible];
By
[self.window setRootViewController:self.viewController];
[self.window makeKeyAndVisible];
You can use the delegate
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return UIInterfaceOrientationLandscapeLeft;
}
Using this delegate and the application will be present in Landscape mode or any desired orientation mode.
Try it.

iPad: How to display a different screen depending on orientation (landscape / portrait)

I have an iPad application that can be used in all four view modes (portrait up/down and landscape left/right). But at a certain point I have a View that I only want to be seen in landscape mode. So I do the following in the UIViewController that will trigger the action to view the landscape-only view:
- (void) showProperty:(Property *) property {
if ([self interfaceOrientation] == UIInterfaceOrientationLandscapeLeft || [self interfaceOrientation] == UIInterfaceOrientationLandscapeRight) {
PropertyViewController *propertyView = [[PropertyViewController alloc] initWithNibName:#"PropertyViewController" bundle:[NSBundle mainBundle]];
propertyView.property = property;
[self.navigationController pushViewController:propertyView animated:YES];
[propertyView release];
propertyView = nil;
}
else {
RotateDeviceViewController *rotateView = [[RotateDeviceViewController alloc] initWithNibName:#"TabRotate" bundle: [NSBundle mainBundle]];
rotateView.property = property;
[self.navigationController pushViewController:rotateView animated:YES];
[rotateView release];
rotateView = nil;
}
}
This works fine and thus shows either the desired screen (PropertyViewController) when the iPad is held in landscape mode, and if not it shows the RotateDeviceViewController which shows the user a message that he/she is supposed to rotate the device to correctly view the screen.
So when the user then rotates his/her device to landscape mode I want to show them the right view (PropertyViewController). And all of this kinda works!
The problem arises though in this RotateDeviceViewController.. There I have the following:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
if (UIInterfaceOrientationIsLandscape(interfaceOrientation))
[self showProperty];
return UIInterfaceOrientationIsPortrait(interfaceOrientation);
}
- (void) showProperty {
PropertyViewController *propertyView = [[PropertyViewController alloc] initWithNibName:#"PropertyViewController" bundle:[NSBundle mainBundle]];
propertyView.property = property;
[self.navigationController pushViewController:propertyView animated:YES];
[propertyView release];
}
So as soon as I rotate the device (when viewing the RotateDeviceViewController) to landscape mode I show the user the PropertyViewController. This works... But when the PropertyViewController appears it shows my layout 90 degrees rotated. So basically it shows the content in portrait mode instead of using the landscape mode (which is actually the way you are holding the device)..
I hope this makes sense and someone can show me what's causing this.
Screenshots to make it more clear:
When device is held in portrait mode
After rotating the device
At this point
- (BOOL)shouldAutorotateToInterfaceOrientation:UIInterfaceOrientation)interfaceOrientation
You are telling the view controller what orientations you support. The device has not actually rotated yet therefore the view controllers intefaceOrientation property will still be portrait so when it is pushed onto the stack it thinks the device is portrait.
pseudo code
shouldAutoRotate... // at this point self.interfaceOrientation == portrait
// you push your controller here so it loads when the property is
I'm not sure if this will work well but the earliest I can see you can push is in
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation

Resources