Force landscape orientation in one view controller - ios7

In iOS 5 and 6 I was doing this in the viewWillAppear method in my view controller:
UIViewController *c = [[UIViewController alloc] init];
//To avoid the warning complaining about the view not being part of the window hierarchy
[[[TWNavigationManager shared] window] addSubview:c.view];
[self presentModalViewController:c animated:NO];
[self dismissModalViewControllerAnimated:NO];
[c.view removeFromSuperview];
I also added this method in the app delegate
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
return [[TWNavigationManager shared] supportedInterfaceOrientationsForTopViewController];
}
Which basically forwards that call to the top view controller.
That caused auto-rotation methods to be called for my view controller and then I was able to force landscape orientation for just that view controller.
Now in iOS 7 that code doesn't work anymore. A white view appears full-screen.
What would be the proper approach in iOS7?
Thanks in advance.

Had the same problem and managed to fix it by dismissing the presented modal view animated:YES.
[self dismissViewControllerAnimated:YES completion:nil];
Hope that helps!

My solution involves what Andrey Finayev suggested, but also I had to set another transition style otherwise I was getting blank screen after the dismiss animation finished.
UIViewController *mVC = [[UIViewController alloc] init];
mVC.modalPresentationStyle = UIModalPresentationFullScreen;
mVC.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[self.navigationController presentViewController:mVC animated:NO completion:^{
[self.navigationController dismissViewControllerAnimated:YES completion:^{
}];
}];

To prevent the little "flashing" from mdonia solution, I added a dispatch_after and was able to dismiss the dummy modal viewController with animation:NO
UIViewController *dummyModalVC = [UIViewController new];
[dummyModalVC setModalPresentationStyle:UIModalPresentationFullScreen];
[dummyModalVC setModalTransitionStyle:UIModalTransitionStyleCrossDissolve];
[dummyModalVC.view setBackgroundColor:[UIColor purpleColor]];
[self presentViewController:dummyModalVC animated:NO completion:^{
double delayInSeconds = 0.001f;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
[dummyModalVC dismissViewControllerAnimated:NO completion:^{}];
});
}];
Looks of course still like an ugly workaround, but I didn't found a better solution in the given timeā€¦ ;(

Related

UIPopoverPresentationController can not be dismissed on iPhone

I'm implementing a CABTMIDICentralViewController (Apple's pre-fab BTLE MIDI configuration panel). The code below is Apple's sample code - unmodified.
It works perfectly on iPad, but on iPhone/iPod it results in an uncloseable fullscreen view. The code clearly creates a Done button, but it isn't shown on the devices.
The common answer is "you need a UINavigationController", but there is one being made in this code. So I'm not sure what else is missing?
- (void)doneAction:(id)sender
{
[self dismissViewControllerAnimated:YES completion:nil];
}
- (IBAction)configureCentral:(id)sender
{
CABTMIDICentralViewController *viewController [CABTMIDICentralViewController new];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:viewController];
// this will present a view controller as a popover in iPad and modal VC on iPhone
viewController.navigationItem.rightBarButtonItem =
[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone
target:self
action:#selector(doneAction:)];
navController.modalPresentationStyle = UIModalPresentationPopover;
UIPopoverPresentationController *popC = navController.popoverPresentationController;
popC.permittedArrowDirections = UIPopoverArrowDirectionAny;
popC.sourceRect = [sender frame];
UIButton *button = (UIButton *)sender;
popC.sourceView = button.superview;
[self presentViewController:navController animated:YES completion:nil];
}
You will have to implement the UIPopoverPresentationControllerDelegate to view popovers in iPhones. By default it will be presented in the style of an already presented view controller.
Add this piece of code to present the controller as popover
- (UIModalPresentationStyle)adaptivePresentationStyleForPresentationController:(UIPresentationController *)controller traitCollection:(nonnull UITraitCollection *)traitCollection {
return UIModalPresentationNone;
}

MBProgressHud with storyboards

The following code is from a sample demo.
HUD = [[MBProgressHUD alloc] initWithView:self.navigationController.view];
[self.navigationController.view addSubview:HUD];
HUD.delegate = self;
HUD.labelText = #"Loading";
[HUD showWhileExecuting:#selector(myTask) onTarget:self withObject:nil animated:YES];
It uses .xibs as it views. I'm creating an application that uses storyboards. Thus there is no navigationController for the initWithView method when instantiating HUD. Is there any way to implement a HUD without using .xibs and a navigationController. I've tried passing both "self" and "self.view" but they don't work. The class that this is in is the ViewController.m class and it is a UIViewController class. So I don't see why passing self wouldn't work.
This is my code
HUD = [[MBProgressHUD alloc] initWithView:self.view];
[self.view addSubview:HUD];
Again "self" is my main ViewController
Thanks!
Here's what I think you want:
MBProgressHUD *hud = [[MBProgressHUD alloc] initWithView:view];
[view addSubview:hud];
[hud showWhileExecuting:#selector(YOUR_TASK) onTarget:YOUR_TARGET withObject:nil animated:YES]; // or NO if you don't want it to be animated
Alternatively, if you want to manage showing and displaying the HUD manually yourself, there's some nice convenience methods for doing that:
// To add HUD to a view
MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:view animated:YES]; // or NO if you don't want it to be animated
// To set HUD text
[hud setLabelText:#"Text"];
// To remove HUD from a view (such as later in the code, after load, etc)
[MBProgressHUD hideHUDForView:view animated:YES];
Where view is the view you want the HUD added/removed from.
I.e. self.view on a view controller.

MBProgressHud does not work on navigation bar

I have a buttono in the navigation item which action is BUTTON_ACTION. By pressing it, MBProgressHUD is activate and the action work. but the "dimBackground" that make "hidden" the scrren, doe not work on the navigationbar, and the button can be pressed again during the MBProgressHUD.
The code is:
HUD = [[MBProgressHUD alloc] initWithView:self.view];
[self.view addSubview:HUD];
// Regiser for HUD callbacks so we can remove it from the window at the right time
HUD.delegate = self;
HUD.labelText=#"Buscando Bares...";
HUD.dimBackground = YES;
// Show the HUD while the provided method executes in a new thread
[HUD showWhileExecuting:#selector(BUTTON_ACTION) onTarget:self withObject:nil animated:YES];
I tryed to use:
HUD = [[MBProgressHUD alloc] initWithView:self.navigationController.view];
[self.navigationController.view addSubview:HUD];
Any idea about that? thanks in advance.
To make the MBProgressHUD being displayed above all UI controls including the UINavigationBar you must do this:
HUD = [[MBProgressHUD alloc] initWithWindow:self.view.window];
[self.view.window addSubview:HUD];
#ararog is right, but it's also simple to just do
_progressHUD = [MBProgressHUD showHUDAddedTo:self.view.window animated:YES];

Why is my UInavigationController right button disappearing after it is loaded

I'm using the following code to push a view controller when user click on a UIButton
- (IBAction)showListPicker:(id)sender {
if([audioPlayer isPlaying])
{
[audioPlayer stop];
}
ListPicker *lp = [[ListPicker alloc] initWithStyle:UITableViewStyleGrouped];
[[self navigationController] pushViewController:lp animated:YES];
[lp release];
}
In the ViewDidLoad of ListPicker I use the following code to add right navigational control button
-(void)viewDidLoad{
[[self navigationController] setNavigationBarHidden:NO];
[[[self navigationController] navigationBar] setTintColor:[UIColor brownColor]];
[[self view] setBackgroundColor:[UIColor colorWithPatternImage:[UIImage imageNamed:#"background.png"]]];
UIBarButtonItem *button = [[UIBarButtonItem alloc]
initWithBarButtonSystemItem:UIBarButtonSystemItemAdd
target:self
action:#selector(doSomething:)];
[[self navigationItem] setRightBarButtonItem:button];
[button release];
}
When the view is loaded, I can see the right button briefly but then it disappear right away. What am I doing wrong?
Thank you.
My guess is that your ListPicker's XIB contains another navigation bar, obstructing the actual navigation controller's bar. This is why you see it for an instant and then it "disappears". If it's not something in the XIB, check the code all the way from instantiating that new view controller until the viewDidAppear of ListPicker.

How to make the splash screen sleep for 4 seconds until the user touches the screen in iphone sdk

I am using splash screen for my application when it starts begining and I made it to sleep for 4 seconds.My need is if user taps on the splash screen before the 4 seconds he should navigate to the next screen.Can any one suggest me with some ideas.
My code I tried was:
- (void)applicationDidFinishLaunching:(UIApplication *)application
{
// Override point for customization after application launch
[self createEditableCopyOfDatabaseIfNeeded];
[self initializeDataStructures];
mainController = [[FavoritesViewController alloc] init] ;
navController = [[UINavigationController alloc] initWithRootViewController:mainController];
navController.navigationBar.barStyle = UIBarStyleBlack;
[window addSubview:navController.view];
splashView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 320, 480)];
splashView.image = [UIImage imageNamed:#"default.png"];
[window addSubview:splashView];
[window bringSubviewToFront:splashView];
sleep(4);
// Do your time consuming setup
[splashView removeFromSuperview];
[splashView release];
[window makeKeyAndVisible];
}
Anyone's help will be much appreciated.
Thank's all,
Monish.
Well, you haven't shown us any code or told us what your real problem is, but in pseudo-code I would do something like this:
- (void) start {
[self showSplashScreen];
fourSecondsRunning = YES;
// In four seconds, call stop.
[self performSelector:#selector(stop) withObject:nil afterDelay:4.0];
}
- (void) stop {
// View wasn't tapped during the last 4 seconds. Do something.
fourSecondsRunning = NO;
[self hideSplashScreen];
[self doSomething];
}
- (void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
if (fourSecondsRunning) {
fourSecondsRunning = NO;
// Touched within the four seconds. Make sure "stop" is not called.
[[NSRunLoop currentRunLoop] cancelPerformSelectorsWithTarget:self];
[self hideSplashScreen];
[self goToNextScreen];
}
}