UIImagePickerController with UIPopOverController, iPad ios 6 - ios

I am trying access the Photo Library from an iPad application. It is said that "On iPad, UIImagePickerController must be presented via UIPopoverController". That's exactly the log message that I get too.
Here is a snapshot of my app:
Since I am already listing the options via a popover, it doesn't make sense to go another popover from within. The accessPhotoLibrary method gets called when the user taps on the "Photo Library" cell.
-(void)accessPhotoLibrary{
NSLog(#"Photo library access requested!");
if([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]){
NSLog(#"Photo Library");
[imagePickerController setSourceType:UIImagePickerControllerSourceTypePhotoLibrary];
[imagePickerController setDelegate:self];
[imagePickerController setModalPresentationStyle:UIModalPresentationFullScreen];
[self presentViewController:imagePickerController animated:YES completion:nil];
}
else{
UIAlertView *alert = [[UIAlertView alloc]
initWithTitle: #"Photo Library"
message: #"Sorry, couldn't open your photos library"
delegate: nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
}
}
But how do I get around this problem of having to access the photo library using a popover when I am using one already??
Any help is much appreciated.

You can present the image picker within the same popover. Hold a reference to the popover (the parent view controller presenting the popover can pass a reference) and then you can do the following:
[_parentPopover setContentViewController:imagePickerController animated:YES];
If needed, you can change the size of the content presented in the popover using the property "contentSizeForViewInPopover" in the image picker view controller.

Related

iOS - Picker controller does not open Photo Library

In my app, i use a UIActionSheet and UIImagePickerController. Action Sheet opens optiones (as choose photo, choose video) and Image Picker Controller opens library. This system works good for iPhone device testing but for iPad, Action Sheet works fine while Picker Controller does not.
I have set required permissions for iOS10, for camera and photo library. This cannot be the problem.
My code for selecting photo:
- (void)selectPhoto {
self.imagePickerController.delegate = self;
self.imagePickerController.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
self.imagePickerController.mediaTypes = [NSArray arrayWithObjects:(NSString *)kUTTypeImage, nil];
[self presentViewController:self.imagePickerController animated:YES completion:nil];
}
Required delegate methods were written either. And as I mentioned, everyting works as it should do in iPhones.
When I try to open photo library first I get this warning messages:
[Warning] <_UIPopoverBackgroundVisualEffectView 0x147c5ad0> is being
asked to animate its opacity. This will cause the effect to appear
broken until opacity returns to 1.
Nothing is broken, app is still running (not freezing). However if I try to open photo library, this time I get:
Warning: Attempt to present on
which is already presenting (null)
Then, the problem might be popover problem but I could not find the answer.
Thank you!
Edit: My action sheet delegate method:
-(void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
[actionSheet dismissWithClickedButtonIndex:buttonIndex animated:YES];
switch (buttonIndex) {
case 0:
[self selectPhoto];
break;
case 1:
[self selectVideo];
break;
default:
break;
}
}
Edit 2: I found that:
On iPad, you must present the browser interface using a popover as
described in initWithContentViewController: and Presenting and
Dismissing the Popover in UIPopoverController Class Reference. If, on
iPad, you attempt to present the browser interface modally
(full-screen), the system raises an exception.
UIPopoverController is now deprecated. Thus I should use another way. If anyone can help me about this, I'd be ver happy.
For iPad use the code to open the UIImagePicker
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
[self presentViewController:picker animated:NO completion:nil];
}];
There is a list of all Cocoa Keys that you can specify in your Info.plist file:
https://developer.apple.com/library/mac/documentation/General/Reference/InfoPlistKeyReference/Articles/CocoaKeys.html
iOS already required permissions to access microphone, camera, and media library earlier (iOS6, iOS7), but since iOS10 the apps will crash if you don't provide the description why you are asking for the permission.
On iPad you can't show UIImagePickerController popover over an already onscreen UIActionSheet popover.
Replace
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
with
- (void)actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex;
and it must work.
And remove [actionSheet dismissWithClickedButtonIndex:buttonIndex animated:YES];, as soon as you click on a button, UIActionSheet is dismissed automatically.
To show an image picker on both the iPhone and iPad, you need to present it as a popover.
So the implementation to show your picker would change to
self.imagePickerController.delegate = self;
self.imagePickerController.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
self.imagePickerController.mediaTypes = [NSArray arrayWithObjects:(NSString *)kUTTypeImage, nil];
self.imagePickerController.modalPresentationStyle = UIModalPresentationPopover; //This is needed
self.imagePickerController.sourceView = self.view; //This is needed
[self presentViewController:self.imagePickerController animated:YES completion:nil];
Do make sure your action sheet is dismissed before you present the picker.

Method showing alert in App Delegate fails because it's rootViewController is not in the View Hierarcy

During development of my iOS application, I would like to be able to show the user a dialog if a serious bug occurs.
on SO, found that this could be achieved with adding something like the following to my AppDelegate class
- (void) notifyUserAboutSeriousBugWithMessage:(NSString *)message {
UIAlertController* alert = [UIAlertController alertControllerWithTitle:#"Serious bug: Alert developer"
message:message
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:#"Continue" style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {}];
[alert addAction:defaultAction];
[self.window.rootViewController presentViewController:alert animated:YES completion:^{}];
}
However, when I run this, i get an error message saying I'm Attempting to present <A> on <B> whose view is not in the window hierarchy!
My application is using a storyboard and the Entry/Start point <B> is a Splash Screen (-viewController). [This is not contained in a NavigationController]
When I'm done with the splash screen, I use a Modal Segue to show "the rest" of the app.
So how can I workaround this? In my app delegate, I want to get some view controller that will be in the view hierarcy and show my Alert in it's view.
(The reason I want to put this in the app delegate is that I want to present error alerts from classes that are not view controllers)
Thanks!
That's probably because you already have a presented viewController on top of your rootViewController. You need to present your alert on top of the topmost view controller.
Here is how you can get the topmost controller :
UIViewController *topViewController = self.window.rootViewController;
while (topViewController.presentedViewController) {
topViewController = topViewController.presentedViewController;
}
You can then do :
[topViewController presentViewController:alert animated:YES completion:nil];

UIAlertView is not positioned at the center of the screen

I have to fix some bugs in an old application and got a really weird one. All alert views are shown in the top left corner for some reason. App doesn't use storyboards, main window is loaded from xib. What can cause this?
UPDATE: Code to initialize alert view is pretty standard. I'm calling it inside one of the controllers of UITabBarController. Same bug occurs even if I leave app's main window empty and initialize alert view in application:didFinishLaunchingWithOptions:
UIAlertView *testAlert = [[UIAlertView alloc] initWithTitle:#"Title"
message:#"Message"
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil, nil];
[testAlert show];
I fixed this by simply replacing the [alert show] with the present [self presentViewController:alert animated:YES completion:nil];

MFMessageComposeViewController addAttachmentData on iPad iOS7 black screen

I have a MFMessageComposeController, and I want to send images via iMessage (SMS not available on my iPad).
This is my code:
- (void)presentMessageController {
if(![MFMessageComposeViewController canSendAttachments])
{
UIAlertView *warningAlert = [[UIAlertView alloc] initWithTitle:#"Error"
message:#"Your device doesn't support sharing photos via SMS!"
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[warningAlert show];
return;
}
MFMessageComposeViewController *messageController = [[MFMessageComposeViewController alloc] init];
messageController.messageComposeDelegate = self;
[messageController addAttachmentData:imgData typeIdentifier:(NSString *)kUTTypePNG filename:#"image.png"];
// Present message view controller on screen
[self presentViewController:messageController animated:YES completion:nil];
}
The problem seems to be in [messageController addAttachmentData...]. The messageController is not presented, instead a blank screen appears, and app is hanging up, and after 1-2seconds, the delegate responds with MessageComposeResultCancelled, and I see this in console:
timed out waiting for fence barrier from com.apple.mobilesms.compose
Warning: Attempt to dismiss from view controller while a presentation or dismiss is in progress!
If I comment that line, the messageController is presented (iMessage is opened).
IMPORTANT:
This is happening when testing on iPad (I tested on iPad 2 only, with iOS 7.0.3 installed). Same code works perfect in iPhone 5, 4, 4S with iOS 7.0.3.
When black screen appears, there is no way to return to app. You have to terminate the app, and restart.
Anybody experiencing same issue? Please help. Thanks.
try changing:
[messageController addAttachmentData:imgData typeIdentifier:(NSString *)kUTTypePNG filename:#"image.png"];
to:
[messageController addAttachmentData:imgData typeIdentifier:#"public.data" fileName:#"image.png"];
Call presentMessageController method after some delay
[self performSelector:#selector(presentMessageController) withObject:nil afterDelay:0.5];

Is it possible to display an image over a photo taken in app

Is it possible to have a series of images (pngs) that can be positioned either over the top of an image taken in app or just appear on the screen when in camera mode in app? ie a door or wallpaper sample.
If so how might this be achieved?
Thanks for any help given :)
UIImagePickerController has a cameraOverlayView UIView property. Assign it whatever you want to be on top of the camera.
From the docs:
You can use an overlay view to present a custom view hierarchy on top of the default image picker interface. The image picker layers your custom overlay view on top of the other image picker views and positions it relative to the screen coordinates. If you have the default camera controls set to be visible, incorporate transparency into your view, or position it to avoid obscuring the underlying content.
This may help you.
-(IBAction)loadCameraView:(id)sender
{
if([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera])
{
UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init];
[imagePicker setSourceType:UIImagePickerControllerSourceTypeCamera];
if ([UIImagePickerController isCameraDeviceAvailable:UIImagePickerControllerCameraDeviceFront])
{
[imagePicker setCameraDevice:UIImagePickerControllerCameraDeviceFront];
}
else
{
[imagePicker setCameraDevice:UIImagePickerControllerCameraDeviceRear];
}
[imagePicker setCameraCaptureMode:UIImagePickerControllerCameraCaptureModePhoto];
[imagePicker setDelegate:self];
[self presentViewController:imagePicker animated:YES completion:nil];
}
else
{
UIAlertView *aview = [[UIAlertView alloc] initWithTitle:#"Camera Not Available" message:nil delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil, nil];
[aview show];
}
}

Resources