UIPopovercontroller dealloc reached while popover is still visible - ios

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

Related

How do I solve gallery scroll stuttering in a landscape-oriented UIImagePickerController?

I have tried a couple of different methods for presenting a landscape-oriented UIImagePickerController in a landscape-only app (not by my choice) I'm working on.
When I (successfully) present the gallery in landscape format and scroll through the images, there is a truly horrible stutter!
The current technique I am using is this:
- (void)presentImagePickerController:(UIImagePickerControllerSourceType)sourceType {
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
if (isDeviceIPad) {
picker.modalPresentationStyle = UIModalPresentationFormSheet;
picker.preferredContentSize = [UIScreen mainScreen].bounds.size;
}
picker.sourceType = sourceType;
picker.delegate = self;
picker.allowsEditing = YES;
[self presentViewController:picker
animated:YES
completion:nil];
}
I cannot go with a solution which uses private interfaces, since the app has to pass App Store review. I'd prefer not to use a third-party library, since my boss is against that idea.
My iPad is a 3rd generation, model MD334LL/A that's running iOS 8.1.
From the UIImagePickerController class reference found here: https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIImagePickerController_Class/index.html
On iPad, the correct way to present an image picker depends on its source type, as summarized in this table:
Camera: Use full screen
Photo Library: Must use a popover
Saved Photos Album: Must use a popover
Answer: Since I want to present the Saved Photos Album, I need to present the picker by using a popover.
- (void)presentImagePickerController:(UIImagePickerControllerSourceType)sourceType {
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.sourceType = sourceType;
picker.delegate = self;
picker.allowsEditing = YES;
if (isDeviceIPad() && sourceType == UIImagePickerControllerSourceTypeSavedPhotosAlbum) {
picker.modalPresentationStyle = UIModalPresentationPopover;
UIPopoverPresentationController *presentationController = picker.popoverPresentationController;
presentationController.permittedArrowDirections = UIPopoverArrowDirectionAny;
presentationController.sourceView = self.presentPickerButton;
presentationController.sourceRect = self.presentPickerButton.bounds;
}
[self presentViewController:picker
animated:YES
completion:nil];
}

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.

UIImagePickerController really slow when calling alloc init

I have a view controller that is presented on pressing on one of the tabs in a tabBarController. In this view controller I initialise a UIImagePickerController in the viewDidLoad method:
- (void)viewDidLoad
{
[super viewDidLoad];
//Set imagePicker
//-------------------------//
_imagePicker = [[UIImagePickerController alloc] init];
_imagePicker.delegate = self;
_imagePicker.videoMaximumDuration = 10.0f;
}
The intention is to then display the UIImagePickerController at a later time when a button is pressed. For some reason though when the tab icon is pressed for this view controller, there is a 3-4 second hang while this viewDidLoad method is running. When I comment out the line _imagePicker = [[UIImagePickerController alloc] init] there is no hang time and the view controller loads immediately - as it should.
Does anyone know why allocating and initialising the UIImagePickerController is taking so long? If so, is there a way to speed it up other than running it as a background process? It seems like this is not normal behaviour.
I am using iOS7, and I am not calling viewWillAppear or viewDidAppear.
Turns out this is only a problem when in debug mode (when the iPhone is connected and running through Xcode). Once the same app is running without being connected to Xcode the lag doesn't occur.
Try this iOS 12
//show a HUD or activityIndicator
dispatch_async(dispatch_queue_create("openPhotosCamera", NULL), ^{
UIImagePickerController *mediaUI = [[UIImagePickerController alloc] init];
dispatch_async(dispatch_get_main_queue(), ^{
//hide HUD or activityIndicator
[presenter presentViewController:mediaUI animated:YES completion:nil];
});
});
**presenter is yourViewController / self
Try this.
- (void)viewDidLoad{
//Set imagePicker
//-------------------------//
_imagePicker = [[UIImagePickerController alloc] init];
_imagePicker.delegate = self;
_imagePicker.videoMaximumDuration = 10.0f;
[super viewDidLoad];

my popovercontroller terminating

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

Apple's controllers not presenting properly in iOS7

In my iOS app i present standerd controllers MFMessageComposeViewController and UIImagePickerController.
But they both presenting with strange navigation bar.
How can i fix this problem?
UPD code for presenting controllers
UIImagePickerController:
UIImagePickerController *cameraUI = [[UIImagePickerController alloc] init];
cameraUI.sourceType = sourceType;
cameraUI.allowsEditing = YES;
cameraUI.delegate = self;
[self presentViewController:cameraUI animated:YES completion:nil];
MFMessageComposeViewController:
MFMessageComposeViewController *messageViewController = [[MFMessageComposeViewController alloc] init];
if([MFMessageComposeViewController canSendText]) {
messageViewController.view.backgroundColor = [UIColor whiteColor];
messageViewController.messageComposeDelegate = self;
recipient= [NSStringMask maskString:recipient withPattern:#"\\+(\\d{1}) \\((\\d{3})\\) (\\d{3})-(\\d{2})-(\\d{2})"];
messageViewController.recipients = #[recipient];
messageViewController.body = body;
[self presentViewController:messageViewController animated:YES completion:nil];
}
In iOS 7, the status bar and the navigation is translucent by default. To make the view act 'normal' like in iOS 6. you need to add this to the controller you are presenting.
if ([self respondsToSelector:#selector(edgesForExtendedLayout)])
self.edgesForExtendedLayout = UIRectEdgeNone;
If you want to read up more about changes in views. Check out this post. I find it a nice quick overview whats changed.
http://www.brianjcoleman.com/ios7-weve-got-a-problem/
See this question. I used the second answer, though I suspect the first would work for me also.

Resources