my popovercontroller terminating - ios

I am creating image based application.Now I have allocated and synthesized pickerviewcontroller in my viewcontroller.m class.
as UIImagePickerController *picker. Here I have Give it to the (IBAction).
-(IBAction)selectphoto:(id)sender
{
picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
picker.allowsEditing = YES;
picker.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;
[self presentViewController:picker animated:YES completion:NULL];
}
Then i have set it`s delegate methods.
Now, In my another class named as imagedisplay.m,I have created one Button, at which i want to create popupviewcontroller with my imagepickercontroller images(which is in my viewcontroller class),
Below is my code,
-(IBAction)gallery:(id)sender
{
NSLog(#"pop over done.");
ViewController *vcntrlr = [[ViewController alloc] init];
UIPopoverController *popover_=[[UIPopoverController alloc] initWithContentViewController:vcntrlr.picker];
[popover_ setDelegate:self];
[popover_ presentPopoverFromRect:CGRectMake(100, 280,100,100) inView:self.view permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
}
I expecting for Displaying popover controller.BUt when i tryng to press Button((IBAction)gallery) my application is terminated and seems below error.
"terminating with uncaught exception of type NSException".
Help me .

My first guess would be that you are not holding any strong reference to the popovercontroller, so it will be released outside the scope of the -(IBAction)gallery:(id)sender method. To ensure the popover controller is kept alive after the method has finished, you should keep a strong reference to it.
To do so you can add a property to your class:
#property (strong, nonatomic) UIPopoverController* popoverController;
And change your code into:
self.popoverController = [[UIPopoverController alloc] initWithContentViewController:vcntrlr.picker];
[self.popoverController setDelegate:self];
[self.popoverController presentPopoverFromRect:CGRectMake(100, 280,100,100) inView:self.view permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];

Related

UIPopoverController not triggering delegate methods

I'm trying to detect when a UIPopoverController gets dismissed, but it seems not to work properly, the methods are not getting called. This is my code for presenting the UIPopoverController:
UIImagePickerController *imagePickerController = [[UIImagePickerController alloc] init];
imagePickerController.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
imagePickerController.delegate = self;
UIPopoverController *popoverVC = [[UIPopoverController alloc] initWithContentViewController:imagePickerController];
popoverVC.delegate = self;
[popoverVC presentPopoverFromRect:CGRectMake(self.frame.origin.x,self.frame.origin.y, self.frame.size.width, self.frame.size.height) inView:[home view] permittedArrowDirections:0 animated:YES];
I'm trying to fire this method, but is not getting called:
- (void) popoverControllerDidDismissPopover:(UIPopoverController *) popoverController;
And I'm indeed adding the delegate to the header:
#interface Map : UIView <UIImagePickerControllerDelegate, UINavigationControllerDelegate, UIGestureRecognizerDelegate, UIScrollViewDelegate,UIPopoverControllerDelegate>
I don't know what I'm missing out, is not working at all.
You probably already solved it, but I just faced the same problem. I'm holding a instance of UIPopoverController in my Viewcontroller and had it this way:
self.popover.delegate = self;
self.popover = [[UIPopoverController alloc] initWithContentViewController:wgtvc];
of course this doesn't work because I'm initializing the UIPopoverController AFTER setting the delegate, which overrides the delegate setting. So the correct way is to FIRST initialize the UIPopovercontroller and THEN setting the delegate
self.popover = [[UIPopoverController alloc] initWithContentViewController:wgtvc];
self.popover.delegate = self;
Maybe you are reinitializing your UIPopoverController somewhere - just set the delegate again after reinitializing.
Hpoe this helps.
So, I figured out how to make it work.
I made a "global" variable for the class.
self.popoverVC = [[UIPopoverController alloc] initWithContentViewController:imagePickerController];
self.popoverVC.delegate = self;
Because it's an UIImagePickerController inside a UIPopoverController, I needed to listen to the UIImagePickerController for dismission too and combine both methods:
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker;
- (void) popoverControllerDidDismissPopover:(UIPopoverController *) popoverController
So I can now detect when the UIPopoverController gets dismissed.

popoverControllerDidDismissPopover method is not called

In my application I have a presentViewController, and inside it I have a button that opens a popover. In this popover I have a barButtonItem to save de data of this popover. I would like that when the user taps outside of the popover, the data could be saved too.
I've tried to use the popoverControllerDidDismissPopover method in the presentViewController view. I have the delegate but when I tap outside of the popover this method is not called.
What can I do?
Thanks!!
Add this line of code while adding popOver:
popover.delegate = self;
Also register popOverDelegate in .h file where u present your popOver COntroller
#interface yourViewController : UIViewController<UIPopoverControllerDelegate>
Please, pay attention to docs!
"Called on the delegate when the user has taken action to dismiss the popover.
This is not called when the popover is dismissed programmatically."
It was my case because my popover was closing on button tap with this method:
dismiss(animated: true, completion: nil)
You probably already solved it, but I just faced the same problem. I'm holding a instance of UIPopoverController in my Viewcontroller and had it this way:
self.popover.delegate = self;
self.popover = [[UIPopoverController alloc] initWithContentViewController:wgtvc];
of course this doesn't work because I'm initializing the UIPopoverController AFTER setting the delegate, which overrides the delegate setting. So the correct way is to FIRST initialize the UIPopovercontroller and THEN setting the delegate
self.popover = [[UIPopoverController alloc] initWithContentViewController:wgtvc];
self.popover.delegate = self;
Maybe you are reinitializing your UIPopoverController somewhere - just set the delegate again after reinitializing.
I had the same problem and I solved it by handling it different for iOS8.
Presentation code
UIViewController *searchViewController = [[UIViewController alloc] init];
[[searchViewController view] addSubview:_searchOptions];
[searchViewController setModalPresentationStyle:UIModalPresentationPopover];
[searchViewController setPreferredContentSize:CGSizeMake(500, 400)];
[_searchOptions setHidden:NO];
[_searchOptions setFrame:[[searchViewController view] bounds]];
[_searchOptions setAutoresizingMask:UIViewAutoresizingFlexibleWidthAndHeight];
if (CRIdiomToolsIsIOS8OrHigher())
{
UIPopoverPresentationController *popOverPresentationController = [searchViewController popoverPresentationController];
[popOverPresentationController setDelegate:self];
[popOverPresentationController setSourceView:[_searchOptionsButton disclosureView]];
[popOverPresentationController setSourceRect:[[_searchOptionsButton disclosureView] bounds]];
[self presentViewController:searchViewController animated:YES completion:nil];
}
else
{
UIPopoverController *popOverControler = [[UIPopoverController alloc] initWithContentViewController:searchViewController];
[popOverControler setDelegate:self];
[popOverControler setPopoverContentSize:CGSizeMake(500, 400)];
[popOverControler presentPopoverFromRect:[[_searchOptionsButton disclosureView] bounds] inView:[_searchOptionsButton disclosureView] permittedArrowDirections:UIPopoverArrowDirectionUp|UIPopoverArrowDirectionLeft animated:YES];
}
Delegate calls
#pragma mark Delegate Methods: UIPopoverControllerDelegate
- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController
{
[self showSearchOptions:NO animated:YES];
}
#pragma mark Delegate Methods: UIPopoverPresentationControllerDelegate
- (void)popoverPresentationControllerDidDismissPopover:(UIPopoverPresentationController *)popoverPresentationController
{
[self showSearchOptions:NO animated:YES];
}
I had the same issue. You will need to retain the popover object, that way the delegate method gets called. Its strange but it works.
#property (nonatomic, retain) UIPopoverController *popupObject;
UIPopoverController *popup = [[UIPopoverController alloc] initWithContentViewController:viewController];
popup.delegate = self;
[popup presentPopoverFromRect:presentationRect inView:self permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
self.popupObject = popup; //Retained
-(void) popoverControllerDidDismissPopover:(UIPopoverController *)popoverController
{
//Do whatever operation you need to perform
self.popupObject = nil;
}
I know this questions is old but hopefully it helps someone out there...
The issue is in the initialization of your popover controller. If you have established the popover segue in the storyboard you need to have a reference to this popover in order for the delegate to be called when it is dismissed.
In your prepare for segue method:
Instead of:
self.popoverController = [[UIPopoverController alloc]initWithContentViewController:segue.destinationViewController];
self.popoverController.delegate = self;
You need:
self.popoverController = [(UIStoryboardPopoverSegue *)segue popoverController];
self.popoverController.delegate = self;
Then make sure to correctly handle if the when the popover should appear in
(BOOL)shouldPerformSegueWithIdentifier:(NSString *)identifier sender:(id)sender

UIPopoverController does not close

I have a normal UIPopoverController which is made in this way:
-(IBAction)btKBIs_click:(id)sender
{
if(kbiPopOver != NULL)
[kbiPopOver dismissPopoverAnimated:YES];
KBIViewController *kbiViewController = [[KBIViewController alloc]initWithNibName:#"KBIViewController" bundle:nil CurrentUser:currentUser];
kbiViewController.currentStatus = FIRST;
kbiViewController.firstlist = [currentUser getDescriptions];
kbiViewController.mapViewController =self;
UINavigationController* kbiNavController = [[UINavigationController alloc] initWithRootViewController:kbiViewController];
kbiPopOver = [[UIPopoverController alloc] initWithContentViewController:kbiNavController];
kbiPopOver.delegate = self;
kbiViewController.kbiPopOver = kbiPopOver;
[kbiPopOver presentPopoverFromBarButtonItem:sender
permittedArrowDirections:UIPopoverArrowDirectionUp animated:true];
}
Inside the class KBIViewController I'm calling:
[self.kbiPopOver dismissPopoverAnimated:YES];
[self.kbiPopOver.delegate popoverControllerDidDismissPopover:self.kbiPopOver];
To dismiss it but it does not work. Why?
Did you add the <UIPopOverControllerDelegate> in your class interface and did you implement the – popoverControllerDidDismissPopover: method? Just call the dismissPopoverAnimated: explicitly in your code or in the delgate method, when you tap outside the popover. Remove that [self.kbiPopOver.delegate popoverControllerDidDismissPopover:self.kbiPopOver]; from your code.

UIPopovercontroller dealloc reached while popover is still visible

I assure you that I did look for an answer in SO for my question but none of them were helpful. Here I got a simple code that should present a UIImagePickerController within a UIPopoverController:
-(void)takePicture:(id)sender{
UIImagePickerController *picker=[[UIImagePickerController alloc] init];
picker.delegate=self;
picker.sourceType=UIImagePickerControllerSourceTypeCamera;
picker.allowsEditing=YES;
UIPopoverController *poc=[[UIPopoverController alloc]
initWithContentViewController:picker];
[poc presentPopoverFromBarButtonItem:bbItem
permittedArrowDirections:UIPopoverArrowDirectionAny
animated:NO];
}
Now, even from the first time I get [UIPopoveController dealloc] reached while... error and the program crashes. I'm not doing any retain,relase or autoreleases as per ARC. Is there any special consideration with UIPopoverControllers when benefitting from ARC?
UIPopoverControllers should always be held in an instance variable. It is a good practice to create a strong property for it.
UPDATE:
As of iOS 8 you should be using UIPopoverPresentationController. Then you don't need to keep a reference to the popover because it is managed by the presentation controller.
Code example (works both on iPhone and iPad):
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
picker.sourceType = UIImagePickerControllerSourceTypeCamera;
picker.allowsEditing = YES;
picker.modalPresentationStyle = UIModalPresentationPopover;
UIPopoverPresentationController* popoverPC = picker.popoverPresentationController;
popoverPC.barButtonItem = bbItem;
popoverPC.permittedArrowDirections = UIPopoverArrowDirectionAny;
[self presentViewController:picker animated:YES completion:nil];
When the function exits there are no other reference to the popover controller, so it's deallocated too early.
Try adding it as a member of your class instead.
Tim
Adding what #phix23 answered, create *poc property like this:
#property (nonatomic, retain) IBOutlet UIPopoverController *poc;
and then change
UIPopoverController *poc = [[UIPopoverController alloc]
initWithContentViewController:picker];
for
self.poc = [[UIPopoverController alloc]
initWithContentViewController:picker];

UIPopoverController + UINavigationController = Delegate problems

I have two views setup ( inside a TabBar). The DetailView with a button that calls a PopOver with a NavigationController+UITableView (RootView) loading data from CoreData. I have a problem passing data from the UITableView to the DetailView. I have a protocol declared in RootView and used in the DetailView.
Here is the code I use to create the PopOver from the button because I think I have some delegate issues. Any help will be amazing,
- (IBAction)zoneListButtonController
{
if (self.controladorPopOver == nil) {
ipadrootviewController = [[iPadRootViewController alloc] initWithNibName:#"iPadRootView" bundle:[NSBundle mainBundle]];
UINavigationController *ipadnavController = [[UINavigationController alloc]
initWithRootViewController:ipadrootviewController];
UIPopoverController *popover = [[UIPopoverController alloc] initWithContentViewController:ipadnavController];
self.controladorPopOver = popover;
popover.delegate = self;
self.title = #"Countries";
popover.popoverContentSize = CGSizeMake(320, 300);
[self.controladorPopOver presentPopoverFromRect:CGRectMake(112, 20, 86, 27) inView:self.view permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
[ipadnavController release];
[controladorPopOver release];
}
}
An instance of the SubZone1iPadController doesn't exist when you create the popover in DetailView so you can't set its delegate property directly from the DetailView.
One option is to also add the delegate property to the iPadRootViewController which you can set in the zoneListButtonController method. Then, when ipadrootviewController creates the SubZone1iPadController, pass along the delegate.
So in both ipadrootviewController and SubZone1iPadController, add a delegate property:
#property (nonatomic,assign) id <SubZone1Tap> delegate;
Then, in the zoneListButtonController method, set the delegate property on iPadRootViewController:
ipadrootviewController = [[iPadRootViewController alloc] init...
ipadrootviewController.delegate = self;
Then, where ipadrootviewController creates SubZone1iPadController:
SubZone1iPadController *sz1 = [[SubZone1iPadController alloc] init...
sz1.delegate = self.delegate;
[self.navigationController pushViewController:...
[sz1 release];
Finally, in the DetailView, make sure the delegate method is implemented. For example:
-(void)SubZone1Tap:(NSString *)name
{
NSLog(#"SubZone1Tap, name = %#", name);
//dismiss the popover if that's what you need to do...
[controladorPopOver dismissPopoverAnimated:YES];
}

Resources