UIPopoverPresentationController can not be dismissed on iPhone - objective-c

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;
}

Related

Objective-C Modal View Controller with Transparent Background

I wanted to create a modal View Controller that would have a transparent background but when I tried setting the alpha of the background to 0.5 it just made the view behind it completely black. This is because the background views are being removed after the transition.
self.view.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.5];
[self setModalPresentationStyle:UIModalPresentationFullScreen];
[self setDefinesPresentationContext:YES];
Then presenting View Controller Code
SecondViewController *alertView = [[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil];
[self presentViewController:alertView animated:YES completion:nil];
please look at the link
image/linke.gif
Try this code in the action of the button in the firstViewController to change the view controller and present a new class secondViewController
secondViewController *VC = [self.storyboard instantiateViewControllerWithIdentifier:#"secondViewController"];
VC.view.backgroundColor=[UIColor colorWithWhite:0 alpha:0.1f];
VC.modalPresentationStyle=UIModalPresentationOverCurrentContext;
[self presentViewController:VC animated:NO completion:nil];

UIView in front of everything not rotating with screen?

I have this code:
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
imageView.image = [UIImage imageNamed:#"image.png"];
UIApplication *app = [UIApplication sharedApplication];
[app addSubViewOnFrontWindow:imageView];
...
- (void)addSubViewOnFrontWindow:(UIView *)view {
int count = [self.windows count];
UIWindow *w = [self.windows objectAtIndex:count - 1];
[w addSubview:view];
}
The problem is, when the app rotates, the view on the front doesn't rotate. It just stays in portrait.
How can I get this to rotate normally with the rest of the device?
I haven't tried this, but UIWindow has a property rootViewController
The root view controller for the window.
#property(nonatomic, retain) UIViewController *rootViewController
Discussion
The root view controller provides the content view of the
window. Assigning a view controller to this property (either
programmatically or using Interface Builder) installs the view
controller’s view as the content view of the window. If the window has
an existing view hierarchy, the old views are removed before the new
ones are installed.
The default value of this property is nil.
Availability
Available in iOS 4.0 and later.
Declared In
UIWindow.h
As you should be providing this root view controller you should be able to add it to the rootViewContoller's view, and handle aout rotation correctly.
another solution could be, that you swap the windo with a custom one while presenting your view, with another view controller. this trick in action you can see in the implementation of TSAlertView.
- (void) show
{
[[NSRunLoop currentRunLoop] runMode: NSDefaultRunLoopMode beforeDate:[NSDate date]];
TSAlertViewController* avc = [[[TSAlertViewController alloc] init] autorelease];
avc.view.backgroundColor = [UIColor clearColor];
// $important - the window is released only when the user clicks an alert view button
TSAlertOverlayWindow* ow = [[TSAlertOverlayWindow alloc] initWithFrame: [UIScreen mainScreen].bounds];
ow.alpha = 0.0;
ow.backgroundColor = [UIColor clearColor];
ow.rootViewController = avc;
[ow makeKeyAndVisible];
// fade in the window
[UIView animateWithDuration: 0.2 animations: ^{
ow.alpha = 1;
}];
// add and pulse the alertview
// add the alertview
[avc.view addSubview: self];
[self sizeToFit];
self.center = CGPointMake( CGRectGetMidX( avc.view.bounds ), CGRectGetMidY( avc.view.bounds ) );;
self.frame = CGRectIntegral( self.frame );
[self pulse];
if ( self.style == TSAlertViewStyleInput )
{
[self layoutSubviews];
[self.inputTextField becomeFirstResponder];
}
}
with
#interface TSAlertOverlayWindow : UIWindow
{
}
#property (nonatomic,retain) UIWindow* oldKeyWindow;
#end
#implementation TSAlertOverlayWindow
#synthesize oldKeyWindow;
- (void) makeKeyAndVisible
{
self.oldKeyWindow = [[UIApplication sharedApplication] keyWindow];
self.windowLevel = UIWindowLevelAlert;
[super makeKeyAndVisible];
}
- (void) resignKeyWindow
{
[super resignKeyWindow];
[self.oldKeyWindow makeKeyWindow];
}
//
#end
add a new window, with new rootviewController, and subscribe it to
[[NSNotificationCenter defaultCenter] addObserver:(id) selector:(SEL) name:UIDeviceOrientationDidChangeNotification object:nil];
Windows don't autorotate. Ever. You should be adding this imageView to a UIViewController's view as the UIViewController has built in autorotation.
If you want to use a UIWindow to hold all your views, you will need to write your own transform code to handle rotations.

View Controller Animation in Xcode

I need to animate a view when user click on the button. i am using the following code for animating
App Delegate
ViewController2 *vc2_controller = [[ViewController2 alloc]init];
UINavigationController *baseViewController = [[UINavigationController alloc]initWithRootViewController:vc2_controller];
[self.window addSubview:baseViewController.view];
self.window.rootViewController = vc2_controller;
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:self.viewController];
[self.window addSubview:navigationController.view];
self.viewController = [[vc1controller alloc]initWithNibName:nil bundle:nil];
//ViewController1.m -- This is Working
[self.navigationController pushSlideViewController:self.navigationController];
I created function definition inside the category
//Category
- (void)pushSlideViewController:(UIViewController *)viewController
{
// NSLog(#"In Navigation Controller");
//[UIView transitionWithView:viewController.view duration:0.5 options:UIViewAnimationOptionTransitionFlipFromLeft animations:nil completion:nil];
CGRect screensize = [[UIScreen mainScreen]bounds];
[UIView animateWithDuration:0.5 animations:^{
NSLog(#"In View ANimatin");
CGRect current_rect = viewController.view.frame;
viewController.view.frame = current_rect;
current_rect.origin.x = screensize.size.width-50;
viewController.view.frame = current_rect;
}];
}
Now i am calling ViewController1.m from ViewController2.m -- Animation is Not Working
ViewController1 *view_control = [[ViewController1 alloc]init];
[self.navigationController popSlideViewController:view_control];
//Category
-(void)popSlideViewController:(UIViewController *)viewController
{
CGRect screensize = [[UIScreen mainScreen]bounds];
//NSLog(#"In Pop");
[UIView animateWithDuration:0.5 animations:^{
//View is not coming to original position.
CGRect current_rect = viewController.view.frame;
NSLog(#"In View ANimatin %f",current_rect.origin.x);
viewController.view.frame = current_rect;
current_rect.origin.x = 0.0;
viewController.view.frame = current_rect;
}];
}
Note: i am not using ios5 :-)
Thanks,
You're loading VC2 from VC1, which, as you say, works fine. Then you're trying to load VC1 from VC2, which is where the problem lies - VC1 is still loaded, behind VC2, so you just need to dismiss VC2 in a similar way to how you brought it up in the first place, just animate it back off the screen, remove it from the view, then release it (unless you released it when you showed it). Alternatively you could use the built-in methods,
presentViewController:animated:completion:
and
dismissViewControllerAnimated:completion:
which have their own animation.

ModalView presented from MasterViewController is no longer Full Screen in iOS 5.1

I have a Master/Detail application and have a button on the top right of the MasterViewController in the split view that loads an "Info" view controller using a modal view:
When the button is clicked, the view is loaded, and populates the entire screen in iOS 5.0 and below (this is the behavior that I want):
- (IBAction)showAppInfo:(id)sender
{
InfoViewController *infoViewController = [[InfoViewController alloc]
initWithNibName:#"InfoViewController" bundle:nil];
infoViewController.delegate = self;
[self presentModalViewController: infoViewController animated: YES];
}
However, when I run this in the iOS 5.1 simulator, it no longer populates the entire iPad screen, and only populates what's inside the Master View:
What can I do to make this InfoViewController populate the entire screen in iOS 5.1 as it did before?
I assume you are using UIPopoverController, try this
InfoViewController *infoViewController = [[InfoViewController alloc]
initWithNibName:#"InfoViewController" bundle:nil];
UIPopoverController *popoverController = [[UIPopoverController alloc] initWithContentViewController:infoViewController];
popoverController.popoverContentSize = CGSizeMake(500.0, 583.0);
popoverController.delegate = self;
[popoverController presentPopoverFromRect:sender.bounds inView:sender permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];

UIButton UIPopUpController programmatically

having difficulty getting UIButton Items to show.. I want to place several UIButtons within my UIPopUpController. I'm doing everything in a storyboard and I need to do this section programmatically.
- (void)showPopover:(id)sender
{
if(![popoverController isPopoverVisible])
{
myPopOver = [[PopUp alloc] init];
popoverController = [[UIPopoverController alloc] initWithContentViewController:myPopOver] ;
[popoverController setPopoverContentSize:CGSizeMake(300, 200.0f)];
permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
CGRect rect = (CGRect)[sender frame];
rect.origin.y = self.view.frame.size.height - rect.size.height;
[popoverController presentPopoverFromRect:rect inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}
else
{
[popoverController dismissPopoverAnimated:YES];
}
}
You could use a UINavigationController (it has already a navigation bar where you can attach buttons items) and add it as the content of your UIPopoverController. The UINavigationController can be istantiated using the initWithRootViewController method. In this case the controller would be your Popup class. For example, inside your showPopover method, you could do the following:
PopUp* myPopOver = [[PopUp alloc] init];
UINavigationController* navController = [[UINavigationController alloc] initWithRootViewController:myPopOver];
popoverController = [[UIPopoverController alloc] initWithContentViewController:navController];
// do other stuff here to present you UIPopoverController
[myPopOver release];
[navController release];
Now, inside your PopUp class, within viewDidLoad method, you can customize the UINavigationController navigationBar. For example:
- (void)viewDidLoad {
[super viewDidLoad];
UIBarButtonItem *aButtonItem = [[UIBarButtonItem alloc] initWithTitle:#"Show" style:UIBarButtonItemStylePlain target:self action:#selector(somethingSelector:)];
self.navigationItem.rightBarButtonItem = aButtonItem;
[aButtonItem release];
}
where somethingSelector is like the following:
- (void)somethingSelector:(id)sender
{
// your custom actions
}
EDIT
Alternatively you can avoid to use the UINavigationController and create UIToolbar inside your PopUp class. Inside the UIToolbar you can attach UIBarButtonItems. See UIToolbar Class Reference