UISplitViewController: How to present popover? - objective-c

I've a UISplitViewController which is a UISplitViewControllerDelegate with the following delegate method:
splitViewController:willHideViewController:withBarButtonItem:forPopoverController:
When the iPad is started in Portrait, I would like the Popover from the SplitView to be visible. How can I do that?
I've tried the following code:
- (void)splitViewController:(UISplitViewController *)svc
willHideViewController:(UIViewController *)aViewController
withBarButtonItem:(UIBarButtonItem *)barButtonItem
forPopoverController:(UIPopoverController *)pc
{
//setting the barButtonItem in the toolbar in the detail view.
[pc presentPopoverFromBarButtonItem:barButtonItem permittedArrowDirections:UIPopoverArrowDirectionAny animated:NO];
}
But the above code gives me the following error:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UIPopoverController presentPopoverFromRect:inView:permittedArrowDirections:animated:]: Popovers cannot be presented from a view which does not have a window.'

there only one problem, wrong place to call presentPopover method, splitViewController:*WillHide*ViewController....... so, barButtonItem exist but not present on screen. i used next code and it worked for me.
For handle all cases u need to use 2 methods.
- (void)viewDidAppear:(BOOL)animated
{
if ([[UIDevice currentDevice] orientation] == UIDeviceOrientationPortrait || [[UIDevice currentDevice] orientation] == UIDeviceOrientationPortraitUpsideDown) {
if (self.view.window != nil) {
[_masterPopoverController presentPopoverFromRect:CGRectMake(0, 0, 1, 1) inView:self.view permittedArrowDirections:UIPopoverArrowDirectionUp animated:NO];
}
}
[super viewDidAppear:animated];
}
and
-(void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
if (fromInterfaceOrientation == UIDeviceOrientationLandscapeLeft || fromInterfaceOrientation == UIDeviceOrientationLandscapeRight) {
if (self.view.window != nil) {
[_masterPopoverController presentPopoverFromRect:CGRectMake(0, 0, 1, 1) inView:self.view permittedArrowDirections:UIPopoverArrowDirectionUp animated:NO];
}
}
}

Related

MPMoviePlayerController in iOS 8 navigationBar remain visible after exiting Full Screen

For playing Video I am using MPMoviePlayerController,my app supports only portrait mode but For playing Video I need to support Landscape too. Every thing is working fine till iOS 7.x. In iOS 8.0, After exiting Full screen there remains a navigation bar. Please refer below image.
In App delegate, under supportedInterfaceOrientationsForWindow, following is used.
-(NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
if (self.forceLandscapeRight) {
return UIInterfaceOrientationMaskAll;
}
return UIInterfaceOrientationMaskPortrait;
}
Noe in my controller class for initiating MPMoviePlayerController:
[self.mpMoviePlayerContr setContentURL:object];
[theMoviPlayer prepareToPlay];
self.mpMoviePlayerContr.controlStyle = MPMovieControlStyleEmbedded;
self.mpMoviePlayerContr.scalingMode = MPMovieScalingModeAspectFit;
[self.mpMoviePlayerContr play];
self.mpMoviePlayerContr.view.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight;
self.mpMoviePlayerContr.shouldAutoplay = YES;
[theMoviPlayer setFullscreen:false animated:YES];
Also, I have some notification for entering and exiting Full screen.
- (void) moviePlayerWillEnterFullscreenNotification:(NSNotification*)notification {
ED_APPDelegate.forceLandscapeRight = YES;
[self.mpMoviePlayerContr setFullscreen:YES animated:YES];
[self.mpMoviePlayerContr play];
}
- (void) moviePlayerWillExitFullscreenNotification:(NSNotification*)notification {
ED_APPDelegate.forceLandscapeRight = NO;
[self.mpMoviePlayerContr setFullscreen:NO animated:YES];
[self.mpMoviePlayerContr play];
}
- (void)orientationChanged:(NSNotification *)notification
{
UIDeviceOrientation currentOrientation = [[UIDevice currentDevice] orientation];
ED_APPDelegate.forceLandscapeRight = NO;
if (currentOrientation == UIDeviceOrientationLandscapeLeft ||currentOrientation == UIDeviceOrientationLandscapeRight ) {
[self.mpMoviePlayerContr setFullscreen:YES animated:YES];
[self.mpMoviePlayerContr play];
ED_APPDelegate.forceLandscapeRight = YES;
} else {
if (self.mpMoviePlayerContr.playbackState == MPMoviePlaybackStatePaused) {
[self.mpMoviePlayerContr play];
}
[self.mpMoviePlayerContr setFullscreen:NO animated:YES];
ED_APPDelegate.forceLandscapeRight = NO;
}
}
Above code is working fine in iOS 7.x, but have issue in iOS 8.0.

Warning: Attempt to present ViewController whose view is not present in the window hierarchy

I'm using Vserv complete sdk for addintegeration.I'm calling my adViewController to present my add.if the failed add fails I'm taking to a SplashViewController from my addViewController.But I'm getting this warning
Warning: Attempt to present <SplashViewController: 0x1dd697b0> on <AdViewController: 0x1dd68690>
whose view is not in the window hierarchy! and not able to navigate to my next view that is SplashViewController..I've tried all the methods below is the code.Could u guys help me out:
AdViewController.m
- (void)viewDidLoad
{
[super viewDidLoad];
appDelegate = (AppDelegate*)[[UIApplication sharedApplication] delegate];
// Do any additional setup after loading the view from its nib.
}
-(void)viewDidAppear:(BOOL)animated{
[super viewDidAppear:animated];
if([Util isInternetAvailable])
{
//Initializes SDK
[VservAdManager initializeSDK];
CGRect frame1;
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad)
frame1 = CGRectMake(0,0,1024,768);
else
frame1 = CGRectMake(0,0,320,480);
vservAdView = [[VservAdView alloc] initWithFrame:frame1];
[vservAdView requestAd:self:#"7825":nil];
[self.view addSubview: vservAdView];
}
else{
appDelegate = (AppDelegate *) [[UIApplication sharedApplication] delegate];
appDelegate.window.rootViewController = appDelegate.splashViewController;
[self presentModalViewController:appDelegate.splashViewController animated:NO];
}
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
return (interfaceOrientation == UIInterfaceOrientationLandscapeLeft || interfaceOrientation == UIInterfaceOrientationLandscapeRight);
}
else {
return (interfaceOrientation == UIInterfaceOrientationPortrait || interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown);
}
}
- (void)adReceivedNotification:(VservAdView*)vservAd{
NSLog(#"adReceivedNotification");
}
- (void)adFailedNotification:(VservAdView*)vservAd{
NSLog(#"adFailedNotification");
appDelegate.window.rootViewController = appDelegate.splashViewController;
[self presentViewController:appDelegate.splashViewController animated:NO completion:Nil];
}
- (void)adSkipedNotification:(VservAdView*)vservAd{
NSLog(#"adSkipedNotification");
appDelegate = (AppDelegate *) [[UIApplication sharedApplication] delegate];
appDelegate.window.rootViewController = appDelegate.splashViewController;
[self presentModalViewController:appDelegate.splashViewController animated:NO];
}
SplashViewController.h
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
}
-(void)viewDidAppear:(BOOL)animated{
[super viewDidAppear:animated];
[self setupMovie];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
return (interfaceOrientation == UIInterfaceOrientationLandscapeLeft || interfaceOrientation == UIInterfaceOrientationLandscapeRight);
}
else {
return (interfaceOrientation == UIInterfaceOrientationPortrait || interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown);
}
}
-(void)setupMovie{
NSLog(#"setup Movie");
NSString* moviePath = [[NSBundle mainBundle] pathForResource:#"Splash" ofType:#"mp4"];
NSURL* movieURL = [NSURL fileURLWithPath:moviePath];
playerCtrl = [[MPMoviePlayerController alloc] initWithContentURL:movieURL];
playerCtrl.scalingMode = MPMovieScalingModeFill;
playerCtrl.controlStyle = MPMovieControlStyleNone;
// playerCtrl.view.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(moviePlayBackDidFinish:)
name:MPMoviePlayerPlaybackDidFinishNotification object:nil];
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad){
[playerCtrl.view setFrame:CGRectMake(0, 0, 1024, 768)];
}
else{
[playerCtrl.view setFrame:CGRectMake(0, 120, 320, 240)];
}
// [playerCtrl.view setTransform:CGAffineTransformMakeRotation(-M_PI/2)];
[self.view addSubview:playerCtrl.view];
[playerCtrl setRepeatMode:MPMovieRepeatModeNone];
[playerCtrl play];
}
-(IBAction)moviePlayBackDidFinish:(id)sender{
AppDelegate *appDelegate = (AppDelegate*)[[UIApplication sharedApplication] delegate];
[self presentModalViewController:appDelegate.revealController animated:NO];
appDelegate.window.rootViewController = appDelegate.revealController;
}
Why are you presenting view on self if you set the root view of windows to splashViewController?
appDelegate = (AppDelegate *) [[UIApplication sharedApplication] delegate];
appDelegate.window.rootViewController = appDelegate.splashViewController;
[self presentModalViewController:appDelegate.splashViewController animated:NO];
instead use this
appDelegate = (AppDelegate *) [[UIApplication sharedApplication] delegate];
//appDelegate.window.rootViewController = appDelegate.splashViewController;
[appDelegate.window presentModalViewController:appDelegate.splashViewController animated:NO];

NSInvalidArgumentException error. Not running under UIUserInterfaceIdiomPad

Whilst I understand why im receiving an error
'', reason: '-[UIPopoverController initWithContentViewController:] called when not running under UIUserInterfaceIdiomPad.'
Rectifying it is becoming a bit tricky. My pop over is only required on the ipad and not on the iphone version. I omitted any code for the iphones if statement and still got a crash. . Presuming that I must call a view on iphone as well as its a universal app, I simply called the nib in the if iphone statement, and that didn't work either.
- (IBAction)popZs:(id)sender {
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
if ([popoverController isPopoverVisible]) {
[popoverController dismissPopoverAnimated:YES];
} else {
[self->popoverController setPopoverContentSize: CGSizeMake(601, 571)];
[popoverController presentPopoverFromRect:((UIButton *)sender).bounds
inView:sender
permittedArrowDirections:UIPopoverArrowDirectionUp
animated:YES];
}
}
else {
/////using iPhone/////not sure how to handle this spart
zsTablePop *pop = [[zsTablePop alloc] init];
pop.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[pop presentModalViewController:pop animated:YES];
}
Keep getting same erorr even though im using if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
creation of pop over
.m
#import "ICCircuitDetails.h"
#import "zsTablePop.h" ///////////////pop over xib/////
#interface ICCircuitDetails ()
{
zsTablePop *controller;
UIPopoverController *popoverController;
}
///////more code/////////////
- (id)initWithCircuit:(Circuit *)circuit
{
self = [super initWithCertificate:circuit.distributionBoard.certificate];
if (self) {
self.circuit = circuit;
[[NSBundle mainBundle] loadNibNamed:#"ICCircuitDetails" owner:self options:nil];
self.view.contentSize = CGSizeMake(self.contentView.frame.size.width, self.contentView.frame.size.height);
///////////other code here/////////////////
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad)
controller = [[zsTablePop alloc] initWithNibName:#"zsTablePop" bundle:nil];
popoverController = [[UIPopoverController alloc] initWithContentViewController:controller];
Your error message says you try to instantiate a popover. The code only is about presenting it. You need to handle the instantiation as well.

iOS - Change View with the device orientation

I'm using iOS5 and storyboard. I have two view with two different identifier.
I want change the view when change the orientation of the device.
This is my code:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
if(((interfaceOrientation == UIInterfaceOrientationLandscapeLeft) ||
(interfaceOrientation == UIInterfaceOrientationLandscapeRight))){
self.view = [self.storyboard instantiateViewControllerWithIdentifier:#"Landscape"];
}
else if(((interfaceOrientation == UIInterfaceOrientationPortrait) ||
(interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown))){
self.view = [self.storyboard instantiateViewControllerWithIdentifier:#"Portrait"];
}
return YES;
}
But the app crash.
Which is the problem?
EDIT:
If I add two uiview and I put the two id to the uiview when I rotate the device It crash.
This is the code:
- (void)viewDidLoad
{
[super viewDidLoad];
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(orientationChanged:) name:#"UIDeviceOrientationDidChangeNotification" object:nil];
}
- (void) orientationChanged:(id)object
{
portraitView = [self.storyboard instantiateViewControllerWithIdentifier:#"TermoregolatoreTop"];
landscapeView = [self.storyboard instantiateViewControllerWithIdentifier:#"Landscape"];
UIInterfaceOrientation interfaceOrientation = [[object object] orientation];
if (interfaceOrientation == UIInterfaceOrientationPortrait || interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown)
{
self.view = self.portraitView;
}
else
{
self.view = self.landscapeView;
}
}
self.view = [self.storyboard instantiateViewControllerWithIdentifier:#"Portrait"];
Will return an id to a UIViewController and you are assigning it to a UIView.
You have to remove the observer on UIDeviceOrientationDidChangeNotification when releasing the view controller.
The crash happens because that notification is triggered on the class which most likely has been removed from memory.

iOS: UIImagePickerController and ResignFirstResponder

I have an application that allows the user to select a photo from their camera roll, and display it in a UIImageView. But, after they tap on which image they would like to display, the camera roll's view does not disappear. So, I figured that I would need to simply call [sender resignFirstResponder];. But, this did not do the trick. I've been trying multiple things and doing searching around, but to no avail. I'm very new to Objective-C, so any help is much appreciated. Here is the code I'm working with:
(imgPicker is the UIImagePickerController.)
- (IBAction)grabImage(id)sender {
self.imgPicker = [[UIImagePickerController alloc] init];
self.imgPicker.delegate = self;
self.imgPicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
_popover = [[UIPopoverController alloc] initWithContentViewController:imgPicker];
[_popover presentPopoverFromRect:self.imageView.bounds inView:self.imageView permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}
else {
[self presentModalViewController:imgPicker animated:YES];
}
[self.imgPicker resignFirstResponder];
}
And this may or may not be relevant to the issue:
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingImage:(UIImage *)img editingInfo:(NSDictionary *)editInfo {
if (imageView.image == nil) {
imageView.image = img;
[[picker parentViewController] dismissModalViewControllerAnimated:YES];
return;
}
if (imageView2.image == nil) {
imageView2.image = img;
[[picker parentViewController] dismissModalViewControllerAnimated:YES];
return;
}
}
You need just this line to dismiss modal picker in your delegate method:
[picker dismissModalViewControllerAnimated:YES];
resignFirstResponder in this case is useless
Try
[self dismissModalViewControllerAnimated:YES];
As you want to dismiss only picker view and not parent view of picker
you just have to use:
[picker dismissModalViewControllerAnimated:YES];
and you are done.