iOS app with camera popup - ios

I am developing an iOS 7 app in xcode 5. I am using the camera functionality. When the user presses the camera button in my app, I want to give him a choice: take a new picture or choose a picture from the "photostream". I want to show a popup with the choice like "WhatsApp" does, or like the Apple Message app.
I thought; I create an Table View Controller with a section and three cells: take a picture, choose from "photostream" and cancel. I set this section at the bottom of the Table View and make the background transparent. But is does not work ;)
I also searched on Google, but I did not found anything that could help me.
Can anyone tell me how I could do it?

Try this. You have to use UIActionSheetDelegate and UIImagePickerControllerDelegate
- (IBAction)changePhotoButtonPressed:(id)sender {
UIActionSheet *actionSheet=[[UIActionSheet alloc] initWithTitle:#"MY APP"
delegate:self
cancelButtonTitle: nil
destructiveButtonTitle: nil
otherButtonTitles:#"Take From Camera",#"Select From Library", #"Cancel", nil];
actionSheet.actionSheetStyle = UIActionSheetStyleBlackOpaque;
actionSheet.destructiveButtonIndex=2;
[actionSheet showInView:[UIApplication sharedApplication].keyWindow];
}
UIActionSheet Delegate
-(void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
if (buttonIndex==0) {
[self takePictureFromCamera];
}
else if (buttonIndex==1) {
[self pickImageFromLibrary];
}
}
Other Methods:
-(void) pickImageFromLibrary
{
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]) {
UIImagePickerController* imgPicker=[[UIImagePickerController alloc] init];
self.imagePicker = imgPicker;
//UI Customization
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0) {
[[self.imagePicker navigationBar] setTintColor:[UIColor whiteColor]];
}
self.imagePicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
self.imagePicker.delegate = self;
[self presentViewController:self.imagePicker animated:YES completion:nil];
} else {
NSLog(#"Attempted to pick an image with illegal source type '%d'", UIImagePickerControllerSourceTypePhotoLibrary);
}
}
-(void) takePictureFromCamera
{
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
UIImagePickerController* imgPicker=[[UIImagePickerController alloc] init];
self.imagePicker = imgPicker;
self.imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera;
self.imagePicker.delegate = self;
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0) {
[[self.imagePicker navigationBar] setTintColor:[UIColor whiteColor]];
}
[self presentViewController:self.imagePicker animated:YES completion:nil];
} else {
NSLog(#"Attempted to pick an image with illegal source type '%d'", UIImagePickerControllerSourceTypePhotoLibrary);
UIAlertView* alert = [[UIAlertView alloc] initWithTitle:#"MY APP" message:#"CAMERA_NOT_AVAILABLE" delegate:self cancelButtonTitle:#"OK" otherButtonTitles: nil];
[alert show];
}
}

You should use an UIImagePickerController and set its type to either UIImagePickerControllerSourceTypeCamera or UIImagePickerControllerSourceTypePhotoLibrary.
And for the popup with the choices, use an UIActionSheet.
You can have a look at this sample code form Apple for the UIImagePickerController:
https://developer.apple.com/library/ios/samplecode/PhotoPicker/Introduction/Intro.html

Related

Attempt to present UIImagePickerController on UITabBarController while a presentation is in progress

I need help for resolving a warning error. I use a UIImagePickerController and it's showing when I tap on the third tab on my tabBar. When I cancel, I want to show the last tab before the selection of the camera, but when I dismiss my picker, I get a warning!!
This is my code and I don't understand why I get the warning...
-(void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
[self showPickerController];
}
- (void) showPickerController
{
imagePicker = [[UIImagePickerController alloc] init];
if([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]){
imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera;
imagePicker.delegate = self;
} else{
UIAlertView *message = [[UIAlertView alloc] initWithTitle:#"Erreur !"
message:#"Votre iPhone n'a pas de Camera"
delegate:self
cancelButtonTitle:#"Ok"
otherButtonTitles:nil];
[message show];
}
[self presentViewController:imagePicker animated:NO completion:nil];
}
#pragma mark - Camera Methods
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker {
[self.tabBarController dismissViewControllerAnimated:NO completion:^{
if(self.tabBarController!=nil)
[self.tabBarController setSelectedIndex:0];
}];
}
Any idea?
In addition to danh's answer, add a BOOL property to your view controller and add a bit of code to your viewDidAppear: method:
#property (nonatomic) BOOL appeared;
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
if (!self.appeared || [self isMovingToParentViewController] || [self isBeingPresented]) {
self.appeared = YES;
[self showPickerController];
}
}
This will keep the UIImagePickerController from being immediately presented again after being dismissed.
Also, this isn't really relevant to the question, but you might want to change your showPickerController method a bit to prevent from showing an empty UIImagePickerController if there's no camera available:
- (void)showPickerController
{
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
imagePicker = [[UIImagePickerController alloc] init];
imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera;
imagePicker.delegate = self;
[self presentViewController:imagePicker animated:NO completion:nil];
}
else {
UIAlertView *message = [[UIAlertView alloc] initWithTitle:#"Erreur !"
message:#"Votre iPhone n'a pas de Camera"
delegate:self
cancelButtonTitle:#"Ok"
otherButtonTitles:nil];
[message show];
}
}
Simple idea: change this to:
-(void)viewDidAppear:(BOOL)animated{
[super viewDidAppear:animated];
[self showPickerController];
}
Probably a better idea is to detect the source-type-available condition before beginning the transition to this vc, and instead present the picker vc instead.

Error on Presenting FDTake

I got a error on Presenting FDTake (Github-Link) FROM a PRESENTED TableViewController:
Warning: Attempt to present UIImagePickerController: 0x14454a880 on NavigationViewController: 0x14452f900 whose view is not in the window hierarchy!
NavigationViewController is a subclass of UINavigationController. It's from REMenu (https://github.com/romaonthego/REMenu).
Any Idea how I can solve it? I already wrote a Issue to the repository but nobody answered, so I thought maybe you guys know why.
I have never used that library though I can share my code for the same functionality with you. Feel free to use it whereever you were using FDTake. Don't forget to set Actionsheet and UIImagePickerController Delegates.
-(IBAction)chooseProfilePicture:(id)sender
{
UIActionSheet *filterActionSheet = [[UIActionSheet alloc] initWithTitle:#"Select Operation"
delegate:self
cancelButtonTitle:#"Cancel"
destructiveButtonTitle:nil
otherButtonTitles:#"Choose from gallery", #"Take Photo", nil];
[filterActionSheet showInView:self.view];
}
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
{
UIImagePickerController *imgPicker = [[UIImagePickerController alloc] init];
imgPicker.delegate = self;
imgPicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
switch (buttonIndex) {
case 0:
[self.navigationController presentModalViewController:imgPicker animated:YES];
break;
case 1:
if ([UIImagePickerController isSourceTypeAvailable:
UIImagePickerControllerSourceTypeCamera])
{
imgPicker.sourceType =
UIImagePickerControllerSourceTypeCamera;
imgPicker.mediaTypes = #[(NSString *) kUTTypeImage];
imgPicker.allowsEditing = NO;
[self presentViewController:imgPicker
animated:YES completion:nil];
//_newMedia = YES;
}
break;
default:
break;
}
}
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingImage:(UIImage *)img editingInfo:(NSDictionary *)editInfo
{
[picker dismissModalViewControllerAnimated:YES];
//Do what you want with the captured/selected image
}
It's that simple. Not really a need for using third party libs for that. Not an answer to your question but it is relevant in some fashion.

UIImagePickerController doesn't fit into the window when presented

I am trying to develop a simple application which is going to work with the photos the user takes. By following https://developer.apple.com/library/ios/documentation/AudioVideo/Conceptual/CameraAndPhotoLib_TopicsForIOS/Articles/TakingPicturesAndMovies.html I am using a UIImagePickerController in order to take the snapshot. I have a basic application with a single, empty view controller and in the viewDidAppear method I do the following:
- (void)viewDidAppear:(BOOL)animated
{
if ([UIImagePickerController isSourceTypeAvailable:
UIImagePickerControllerSourceTypeCamera] == NO)
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle: #"Error" message: #"Can't use the camera!" delegate: nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert show];
return;
}
UIImagePickerController *cameraUI = [[UIImagePickerController alloc] init];
cameraUI.sourceType = UIImagePickerControllerSourceTypeCamera;
cameraUI.allowsEditing = NO;
cameraUI.delegate = self;
[self presentViewController: cameraUI animated: YES completion:NULL];
}
The resulting view becomes something like:
As you can see the front-rear camera change button doesn't show completely and the UIImagePickerController does not fit into the screen. Should I additionally resize before presenting or am I doing something incorrectly?

UIPopover appearing from wrong button

I have an app which takes an image from existing library, or new from camera.
On the iPad, when I press the 'from library' button the popover appears (correctly) above the button from which it was pressed, however when I press the 'take photo' from the camera button, the camera controller appears over the 'from library' button also... I need this to appear over the 'take photo' button otherwise it looks a bit strange!
here is the code used;
- (void)pickImageFromLibrary: (id)sender
{
[Flurry logEvent: #"PickImage"];
[self openImagePickerWithSourceType: UIImagePickerControllerSourceTypePhotoLibrary];
}
- (void)takePicture: (id)sender
{
[Flurry logEvent: #"TakeImage"];
[self openImagePickerWithSourceType: UIImagePickerControllerSourceTypeCamera];
}
- (void)openImagePickerWithSourceType: (UIImagePickerControllerSourceType)sourceType
{
if ( ![UIImagePickerController isSourceTypeAvailable: sourceType] ) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle: NSLocalizedString( #"Error", #"" )
message: NSLocalizedString( #"We are sorry, but this functionality is not available at your device.", #"No camera eror" )
delegate: nil
cancelButtonTitle: NSLocalizedString( #"Dismiss", #"")
otherButtonTitles: nil];
[alert show];
return;
}
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
picker.sourceType = sourceType;
self.isCameraShown = YES;
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
self.popover = [[UIPopoverController alloc] initWithContentViewController:(UIViewController *)picker];
CGRect takePhotoRect;
takePhotoRect.origin = self.view.frame.origin;
takePhotoRect.size.width = 1;
takePhotoRect.size.height = 1;
[self.popover setPopoverContentSize:CGSizeMake(320.0, 216.0)];
[self.popover presentPopoverFromRect:_openLibraryButton.frame inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}else{
[self presentViewController:picker animated:YES completion:NULL ];
}
}
You are presenting the popover from the openLibraryButton.
[self.popover presentPopoverFromRect:_openLibraryButton.frame inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
You need to add checking to see if the take photo or choose from library button was pressed, then show the popover for that button.
SUDO Code:
if (sourceType == UIImagePickerControllerSourceTypePhotoLibrary) {
[self.popover presentPopoverFromRect:_openLibraryButton.frame inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
} else {
[self.popover presentPopoverFromRect:_takeFromCamera.frame inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}

Displaying ImagePickerController From ActionSheet on iPad

Background: On iPad, I have a button which when tapped, showed a UIActionSheet. This action sheet has 2 options, camera and gallery. Camera when tapped, pulled up a camera and everything works fine. Gallery when tapped, suppose to show a popover with user's photos in it.
Problem: On iPad, UIActionSheet acts like a popover. Which when presenting, another popover cannot come into view. Error:Terminating app due to uncaught exception 'NSGenericException', reason: '-[UIPopoverController dealloc] reached while popover is still visible.
My code:
Setting Action Sheet
- (void)imageButtonTapped:(UIButton *)sender
{
if (_commentObject.image){
_actionSheet = [[UIActionSheet alloc] initWithTitle:#"Action" delegate:self cancelButtonTitle:#"Cancel" destructiveButtonTitle:#"Remove" otherButtonTitles:nil];
_actionSheet.tag = ACTION_IMAGE_REVIEW_TAG;
}else{
_actionSheet = [[UIActionSheet alloc] initWithTitle:#"Image Source" delegate:self cancelButtonTitle:#"Cancel" destructiveButtonTitle:nil otherButtonTitles:#"Camera", #"Gallery", nil];
_actionSheet.tag = ACTION_IMAGE_SOURCE_TAG;
}
if (_isPad) {
[_actionSheet showFromRect:_imageButton.frame inView:_scrollViewContent animated:YES];
}else{
[_actionSheet showInView:self.view];
}
}
Delegate
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
switch (actionSheet.tag) {
case ACTION_IMAGE_SOURCE_TAG:
switch (buttonIndex) {
case 0:
[self pickImage:YES];
break;
case 1:
[self pickImage:NO];
break;
default:
break;
}
break;
}
Executing
- (void)pickImage:(BOOL)fromCamera
{
if (fromCamera) {
if([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]){
UIImagePickerController* cameraPickerController = [[UIImagePickerController alloc] init];
cameraPickerController.sourceType = UIImagePickerControllerSourceTypeCamera;
cameraPickerController.delegate = self;
[self presentViewController:cameraPickerController animated:YES completion:nil];
}else{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Camera Unavailable" message:#"Your Device does not support Cameras" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles: nil];
[alert show];
}
}else{
UIImagePickerController *galleryPickerController = [[UIImagePickerController alloc] init];
galleryPickerController.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
galleryPickerController.delegate = self;
if (_isPad) {
if ([_actionSheet isVisible]) {
[_actionSheet removeFromSuperview];
UIPopoverController *imagePickerPopover = [[UIPopoverController alloc] initWithContentViewController:galleryPickerController];
[imagePickerPopover presentPopoverFromRect:_imageButton.frame inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}
}else{
[self presentViewController:galleryPickerController animated:YES completion:nil];
}
}
}
Question: I tried removing the action sheet from view, and tried dismissing it before executing pickImage. None of that works. How do I present the gallery?
Your Problem: Error:Terminating app due to uncaught exception 'NSGenericException', reason: '-[UIPopoverController dealloc] reached while popover is still visible.
make Object of UIPopoverController in your .h file class. Make sure that your #property for your UIPopoverController is strong instead of weak.
Check this
UIPopoverController: dealloc reached while popover is still visible
UIPopovercontroller dealloc reached while popover is still visible
FYI, This was a comment and OP asked to put it as an answer. Because this solved the issue.
It's happening because you don't have a reference to your UIPopoverController. Have a strong reference for your imagePickerPopover and then try. No problem will occur.
you can try this:
-(void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
{
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
if ([actionSheet isVisible]) {
[actionSheet dismissWithClickedButtonIndex:0 animated:NO];
}
}
}
- (void)actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex
{
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
UIImagePickerController *galleryPickerController = ......
}
}

Resources