UIImagePicker view not removing itself after first use - iphone

I have an app that is adding a view that is used to call UIImagePickerController. When the use hits the add image button, the following code executes:
'- (IBAction)addPhoto:(id)sender {
// Call background tap in case any keyboards are still up
[self backgroundTap:sender];
if (jpegData) {
// If we already chose an image, don't allow to choose another.
// Have to cancel out and come back!
return;
}
// Shows the photo picker so the user can take or select an image
photoPickerViewController = [[PhotoPickerViewController alloc] initWithNibName:#"PhotoPicker" bundle:nil];
photoPickerViewController.delegate = self;
// Add it to the subview - it will auto animate in/out
[self.view addSubview:photoPickerViewController.view];
}
This presents the user with a view that I created that has 3 buttons: Take photo, choose existing photo, and cancel. Cancel just cancels back to the main view. If take photo or choose existing is called, this code is executed:
'- (IBAction)choosePhoto:(id)sender {
// Show an image picker to allow the user to choose a new photo.
UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init];
imagePicker.delegate = self;
if((UIButton*)sender == chooseExistingButton) {
imagePicker.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;
} else {
imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera;
imagePicker.showsCameraControls = YES;
}
[self presentModalViewController:imagePicker animated:YES];
[imagePicker release];
}
When if the user cancels out from the image picker, we go back to the main view. No problem. If however they complete image selection (either through taking a photo or choosing an existing one) then we call:
'- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
// Ok, dismiss the modal picker, bring up the activity indicator and dispatch a thread
// that will do all the photo processing ...
BOOL isFromCamera = picker.sourceType == UIImagePickerControllerSourceTypeCamera;
// Dismiss the picker view controller
[picker dismissModalViewControllerAnimated:NO];
// And remove our view from the list of views
[self.view removeFromSuperview];
if (isFromCamera)
{
// Declare the completion block to use
ALAssetsLibraryWriteImageCompletionBlock compBlock = ^(NSURL *assetURL, NSError *error) {
if (error != nil || assetURL == nil) {
NSLog(#"Failed to save photo: %#", error);
[delegate photoSetURLForImage:nil];
}
else {
NSLog(#"URL is : %#", [assetURL absoluteString]);
[delegate photoSetURLForImage:assetURL];
}
};
ALAssetsLibrary* library = [[[ALAssetsLibrary alloc] init] autorelease];
[library writeImageToSavedPhotosAlbum:cgimage
metadata:meta
completionBlock:compBlock];
return;
}
else {
// Use the URL to get the metadata for the image that was picked ...
NSURL* url = [(NSDictionary*)info objectForKey:#"UIImagePickerControllerReferenceURL"];
if (url) {
// Define a result and failure block for fetching from the ALAsset
ALAssetsLibraryAssetForURLResultBlock resultblock = ^(ALAsset* myasset)
{
ALAssetRepresentation *rep = [myasset defaultRepresentation];
NSLog(#"URL is : %#", [[rep url] absoluteString]);
[delegate photoSetURLForImage:[rep url]];
};
// And also define a failure block
ALAssetsLibraryAccessFailureBlock failureblock = ^(NSError *myerror)
{
[delegate photoSetURLForImage:nil];
};
ALAssetsLibrary* assetslibrary = [[[ALAssetsLibrary alloc] init] autorelease];
[assetslibrary assetForURL:url
resultBlock:resultblock
failureBlock:failureblock];
return;
}
}
// If we get here, something went very wrong
UIAlertView *alert = [[[UIAlertView alloc] initWithTitle:#"Error" message:#"An error occured while retrieving the image" delegate:self cancelButtonTitle:#"Ok" otherButtonTitles:nil] autorelease];
[alert show];
}
Now, the first time I run through this code, all works great. As soon as I hit "use" on the image I took with the camera, or I select an image from the camera roll, the UIImagePicker view and the view that launches it go away and I'm back at the main view while I wait for the ALAsset calls to do their thing.
The problem starts when I try to repeat this process a second time. After selecting an image or taking one, the processing begins, but the views do not go away, until all of the processing by the ALAsset calls has completed. I can't figure out why this is. Why it works the first time, but not anytime after. Is there some caching mechanism I have to clear? Anyways, if anybody can offer up some advice, I'd be very grateful.
Thanks,
J

Yet again it appears I'll be answering my own question. This is starting to become a habit lol.
So it appears that the ALAsset calls aren't spinning off a new thread which is what I thought they were supposed to do. My bad. So to resolve, it was just a matter of spawning a new thread to do all the ALAsset stuff, and in the main thread dismissing my picker and what not.
Problem solved, yay!

Related

App terminates on back button

I have a view controller "Gallery screen" namely, as user taps button "Gallery" it goes to that view controller. Now I have a web service call if any picture of particular outlet exists fetch it or else if it doesn't exist then show an AlertView saying "No image found". Now my problem is when user go to gallery screen if there is no image of that outlet and user hits back button before response of service "no image found" app terminates. I get that popup saying "no image found" on previous screen that i get after pressing back button as i "Ok" it, it terminates but THIS ONLY HAPPENS IN iOS 7. Please help and thanks in advance.
EDIT:
I have also tried to dealloc my objects but still the same issue. May be I'm missing something here is the code that I used.
-(void)dealloc
{
bllGalleryImages.delegate = nil;
bllGalleryImages = nil;
}
here is my viewDidLoad Method
-(void)viewDidLoad
{
[super viewDidLoad];
progress = [[MBProgressHUD alloc] init];
progress.labelText = #"Loading";
[progress showUsingAnimation:YES];
[self.view addSubview:progress];
scrl = [[UIScrollView alloc] initWithFrame:CGRectMake(10, 100, 300, 300)];
scrl.scrollEnabled = YES;
scrl.minimumZoomScale=1.0;
scrl.maximumZoomScale=4.0;
scrl.delegate=self;
// Do any additional setup after loading the view from its nib.
}
here is my View will appear method
-(void)viewWillAppear:(BOOL)animated
{
[self userInterface];
[self callService];
}
here is my callService method
-(void)callService
{
NSMutableDictionary *param = [[NSMutableDictionary alloc] init];
[param setObject:#"xyz" forKey:#"DeveloperKey"];
[param setObject:outletObjForInfo.outlet_id forKey:#"outletID"];
bllGalleryImages = [[BLLAuthentication alloc] init];
bllGalleryImages.delegate = self;
[bllGalleryImages getGalleryImages:param];
}

MBProgress HUD crashing application on reloadData on tableView

I am using this piece of code to display an MBProgressHUD over the top of one of my views while I download data from a web-service, the only problem is that occasionally this code will cause the app to hang, doing nothing while the HUD displays "Downloading" and the screen is locked. Also, if I have something like a keyboard being displayed to the user when I press the refresh button (refresh button performs the download) then the application crashes on the line:
[self.tableView reloadData];
My code:
//Checks for network connection then displays HUD while executing pullAndDisplayData method
- (IBAction) update {
UIAlertView *errorView;
if([[Reachability reachabilityForInternetConnection] currentReachabilityStatus] == NotReachable) {
errorView = [[UIAlertView alloc]
initWithTitle: #"Network Error"
message: #"No Network connection availible!"
delegate: self
cancelButtonTitle: #"OK" otherButtonTitles: nil];
[errorView show];
}
else
{
HUD = [[MBProgressHUD alloc] initWithView:self.navigationController.view];
[self.navigationController.view addSubview:HUD];
HUD.delegate = self;
HUD.labelText = #"Downloading";
HUD.minSize = CGSizeMake(135.f, 135.f);
[HUD showWhileExecuting:#selector(pullAndDisplayData) onTarget:self withObject:nil animated:YES];
}
}
//Downloads this users data from the web-service
- (void) pullAndDisplayData{
// Indeterminate mode
ExpensesDataDownloader *downloader = [[ExpensesDataDownloader alloc] init];
[downloader pullAndDisplayData];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if ([[defaults objectForKey:#"canExportCSVServer"] isEqualToString:#"1"])
{
}
[self.tableView reloadData];
// Switch to determinate mode
HUD.mode = MBProgressHUDModeDeterminate;
HUD.labelText = #"Updating";
float progress = 0.0f;
while (progress < 1.0f)
{
progress += 0.01f;
HUD.progress = progress;
usleep(15000);
}
// The sample image is based on the work by www.pixelpressicons.com, http://creativecommons.org/licenses/by/2.5/ca/
// Make the customViews 37 by 37 pixels for best results (those are the bounds of the build-in progress indicators)
HUD.customView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"37x-Checkmark.png"]];
HUD.mode = MBProgressHUDModeCustomView;
HUD.labelText = #"Completed";
sleep(2);
}
Any help would be much appreciated.
Jack
pullAndDisplayData method is running on a separate thread. This is so that MBProgressHUD can use UI thread to show itself. You should always update your UI from main (UI) thread. Use performSelectorOnMainThread: method to call [self.tableView reloadData]; and other UI stuff. I am assuming that [downloader pullAndDisplayData]; is synchronous call.
From MBprogressHUD API
/**
* Shows the HUD while a background task is executing in a new thread, then hides the HUD.
*
* This method also takes care of autorelease pools so your method does not have to be concerned with setting up a
* pool.
*
* #param method The method to be executed while the HUD is shown. This method will be executed in a new thread.
* #param target The object that the target method belongs to.
* #param object An optional object to be passed to the method.
* #param animated If set to YES the HUD will (dis)appear using the current animationType. If set to NO the HUD will not use
* animations while (dis)appearing.
*/
- (void)showWhileExecuting:(SEL)method onTarget:(id)target withObject:(id)object animated:(BOOL)animated;
Since you are using this method, your pullAndDisplayData is executed in a new thread. This could cause the strange problem you have (I suppose). You are updating the UI elements from a background thread and this is not good. UI elements would be updated form the main thread. Use the background thread to downlaod data only.
Insetad of using it, try to use GCD (Grand Central Dispatch)
[MBProgressHUD showHUDAddedTo:self.view animated:YES];
dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
// download operation here...
dispatch_async(dispatch_get_main_queue(), ^{
[MBProgressHUD hideHUDForView:self.view animated:YES];
// reload data here...
});
});
For further info see Usage section for the MBProgressHUD.
The problem might be occurring due to some memory issue, You try using SVProgressHUD for this, it is the extended version of MBProgressHUD:
You just need to do like this :
- (void) pullAndDisplayData{
[SVProgressHUD showWithStatus:#"Downloading..."];
// Indeterminate mode
ExpensesDataDownloader *downloader = [[ExpensesDataDownloader alloc] init];
[downloader pullAndDisplayData];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if ([[defaults objectForKey:#"canExportCSVServer"] isEqualToString:#"1"])
{
}
[self.tableView reloadData];
// Switch to determinate mode
HUD.mode = MBProgressHUDModeDeterminate;
HUD.labelText = #"Updating";
float progress = 0.0f;
while (progress < 1.0f)
{
progress += 0.01f;
HUD.progress = progress;
usleep(15000);
}
// The sample image is based on the work by www.pixelpressicons.com, http://creativecommons.org/licenses/by/2.5/ca/
// Make the customViews 37 by 37 pixels for best results (those are the bounds of the build-in progress indicators)
HUD.customView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"37x-Checkmark.png"]];
HUD.mode = MBProgressHUDModeCustomView;
HUD.labelText = #"Completed";
sleep(2);
[SVProgressHUD dismiss];
}
No need to allocate or release anything. It works just like that!!!
All the best!!!

UIImagePickerController pixelated image from choosing too quickly, before image fully loaded

I am using UIImagePickerController in an iOS app to save an image in context using UIGraphicsBeginImageContext/UIGraphicsBeginImageContextWithOptions.
I recently noticed that I picture I had saved and then displayed at a later date was highly pixelated; when I went back with the same code and imported the photo again, I got a great image. After playing with this for a while on my device, I figured out that the quality of the image saved depends on WHEN I pressed the 'Choose' button on the 'Move and Scale' screen.
If the image is a larger image and still loading when I press the button, the image is pixelated... if I wait until the image loads, it is fine. My question is, is there any way I can control when the user presses the 'Choose' button - is there any way to force them to wait until after the image is fully loaded? Or is there another way that would be better to approach this issue?
- (void)choosePhoto {
//NSLog(#"%s", __FUNCTION__);
UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init];
imagePicker.delegate = self;
imagePicker.allowsEditing = YES;
imagePicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
[self presentModalViewController:imagePicker animated:YES];
[imagePicker release];
}
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
//NSLog(#"%s", __FUNCTION__);
[self dismissModalViewControllerAnimated:YES];
UIImage *pickedImage = (UIImage*)[info objectForKey:#"UIImagePickerControllerEditedImage"];
[self setPersonImage:pickedImage];
}
- (void) setPersonImage:(UIImage *)pickedImage {
//NSLog(#"%s", __FUNCTION__);
NSManagedObjectContext *context = [[UIApplication sharedDelegate] managedObjectContext];
PersonImage *oldImage = person.image;
if (oldImage != nil) {
[context deleteObject:(NSManagedObject*)oldImage];
}
if (pickedImage != nil) {
// Create an image object for the new image.
PersonImage *newImageObject = [NSEntityDescription insertNewObjectForEntityForName:#"PersonImage" inManagedObjectContext:context];
[newImageObject setImage:pickedImage];
[person setImage:newImageObject];
}
else {
[person setImage:nil];
}
NSError *error;
if (![context save:&error]) {
exit(-1); // Fail
}
}
I suggest you implement your own Crop&Resize view controller.
set imagePicker.allowsEditing = NO.
create your view controller in - (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info and pass selected image to your view controller.
push your view controller to image picker: [picker pushViewController:yourVC animated:YES]
The image captured by the iPhone 4 camera is ~5 MB in size and it takes a while to display/render it. One option is to compress the image using UIImageJPEGRepresentation().
If you do not want to compress the image, you can use UIWebView to display the images. The UIWebViewDelegate has a method - (void)webViewDidFinishLoad:(UIWebView *)webView, that hits after the rendering has been completed. You can enable the choose button in this method (which is disabled initially).

IOS development, using UIImagePickerController and pressing use make the app get stuck (not crash)

Can any one help me with this problem?
As in my last question, I am using a tabBarController with 3 tab items. The 3rd tab is has a uiViewController with a UIImagePickerController in it(a camera).
now every things is working except from one thing. When take an image with the camera and pressing "use" i am getting the alert the the image was save and i can see it in the photo album (if i close the app and look at it) but the app get stuck at this poing and i can not do anything any more. I can see the image on the screen and the "use" and "retake" buttons are not usable. just stuck like that.
Can any one see what am i doing wrong over here?
ps. In all of the examples and tutorials i found there is a release of the picker in the cancel...(also in my code). The picker in my case is a property of the view controller (imgPicker) and i release it as always in the dealloc method, Is that write or wrong? should i live it like that or am i doing a bad memory thing over here (I am not getting any "bad memory error" over here but it might be my mistake...)?
I load the UIImagePicker in the viveWillAppear delegate method.
Every thing is in the same TakePhotoViewController.m file...
-(void) viewWillAppear:(BOOL)animated{
self.imgPicker = [[UIImagePickerController alloc] init];
self.imgPicker.allowsEditing = NO;
self.imgPicker.delegate = self;
self.imgPicker.sourceType = UIImagePickerControllerSourceTypeCamera;
[self presentModalViewController:imgPicker animated:YES];
}
and the delegate methods:
#pragma mark -
#pragma mark - UIImagePicker delegate methods
//saving the image that was taken
- (void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo: (NSDictionary *)info
{
// Access the uncropped image from info dictionary
UIImage *image = [info objectForKey:#"UIImagePickerControllerOriginalImage"];
// Save image
UIImageWriteToSavedPhotosAlbum(image, self, #selector(image:didFinishSavingWithError:contextInfo:), nil);
[picker release];
}
//alerting the user if the images was saved or not
- (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo
{
UIAlertView *alert;
// Unable to save the image
if (error)
alert = [[UIAlertView alloc] initWithTitle:#"Error"
message:#"Unable to save image to Photo Album."
delegate:self cancelButtonTitle:#"Ok"
otherButtonTitles:nil];
else // All is well
alert = [[UIAlertView alloc] initWithTitle:#"Success"
message:#"Image saved to Photo Album."
delegate:self cancelButtonTitle:#"Ok"
otherButtonTitles:nil];
[alert show];
[alert release];
}
//if user is cancelling the camera
-(void)imagePickerControllerDidCancel:(UIImagePickerController *)picker
{
[[picker parentViewController] dismissModalViewControllerAnimated:YES];
[self.tabBarController setSelectedIndex:0];
}
Thank you very much,
Erez
You're on the right track with the Cancel Action, but failed to do it for the other actions:
You need to call dismiss on ViewController after each action.
http://developer.apple.com/library/ios/#DOCUMENTATION/UIKit/Reference/UIImagePickerController_Class/UIImagePickerController/UIImagePickerController.html
EDIT: New link https://developer.apple.com/library/ios/#documentation/UIKit/Reference/UIImagePickerController_Class/UIImagePickerController/UIImagePickerController.html#//apple_ref/doc/uid/TP40007070
... However, if you set this property to YES, your delegate must dismiss
the image picker interface after the user takes one picture or cancels
the operation.
So, if you need to take more than 1 picture, showCameraControls needs to be set to NO, and you need to use your own CameraOverlayView.
Also, definitely DO NOT release picker in your delegate! When the ViewController pops the view, it will release it automatically (Assuming that the picker is not being retained elsewhere). Rule of thumb, if you don't own (retain) it, don't release it. (This concept will probably be forgotten once iOS5 ARC is commonplace)
You should probably release the ViewController after it has been presented.
iPhone - modalViewController release
EDIT: more code to help
-(void) viewWillAppear:(BOOL)animated{
// No need to store... this is 1 use only anyway. Save memory, and release it when done.
UIImagePickerController *imgPicker = [[UIImagePickerController alloc] init];
imgPicker.allowsEditing = NO;
imgPicker.delegate = self;
imgPicker.sourceType = UIImagePickerControllerSourceTypeCamera;
[self presentModalViewController:imgPicker animated:YES];
[imgPicker release]; // Release this here, this will execute when modal view is popped.
}
Delegate:
- (void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo: (NSDictionary *)info
{
/* Do what you need to do then */
[[picker parentViewController] dismissModalViewControllerAnimated:YES];
}
//alerting the user if the images was saved or not
- (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo
{
/* Do what you need to do then */
[[picker parentViewController] dismissModalViewControllerAnimated:YES];
}
//if user is cancelling the camera
-(void)imagePickerControllerDidCancel:(UIImagePickerController *)picker
{
/* Do what you need to do then */
[[picker parentViewController] dismissModalViewControllerAnimated:YES];
}

Exception in iPhone app : Modal transition is already in progress

I have what I believe is a fairly simple application at the moment based on a few tutorials cobbled together. I'm using XCode 3.2.3 in OSX 10.6.4. It started as a standard iPhone "Window Based Application". Using interface builder I have added a Tab Bar Controller using the O'Reilly video tutorial here:
http://broadcast.oreilly.com/2009/06/tab-bars-and-navigation-bars-t.html
In the first Tab I have a standard UIView with two buttons. Both call the same function to display a UIImagePickerController:
-(IBAction) btnPhotoClicked:(id)sender {
UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init];
imagePicker.delegate = self;
if((UIButton *)sender == btnChoosePhoto)
{
imagePicker.allowsEditing = YES;
imagePicker.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;
} else {
imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera;
}
[self presentModalViewController:imagePicker animated:YES];
[imagePicker release];
}
I am running the code inside an emulator so only ever click the button called Choose Photo. When the dialogue is released with a photo chosen this function runs:
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
NSURL *mediaUrl;
mediaUrl = (NSURL *)[info valueForKey:UIImagePickerControllerMediaURL];
if (mediaUrl == nil)
{
imagePuzzle = (UIImage *) [info valueForKey:UIImagePickerControllerEditedImage];
if(imagePuzzle == nil)
{
//--- Original Image was selected ---
imagePuzzle = (UIImage *) [info valueForKey:UIImagePickerControllerOriginalImage];
}
else {
//--- Get the edited image ---
//--- If it was successful the above valueForKey:UIImagePickerControllerEditedImage
//--- would have assigned it already.
}
}
else {
//--- Muppet selected a video
}
// Animate the picker window going away
[picker dismissModalViewControllerAnimated:YES];
ImageViewController *imageViewController = [[ImageViewController alloc] init];
imageViewController.delegate = self;
[self presentModalViewController:imageViewController animated:YES];
[imageViewController release];
}
This is where my problem lies. I've tried many different hacks and iterations but the above code is the simplest to present the problem. When the imageViewController is displayed as a modal dialogue the following exception is thrown:
2010-07-09 15:29:29.667 Golovomka[15183:207] *** Terminating app due to uncaught
exception 'NSInternalInconsistencyException', reason: 'Attempting to begin a modal
transition from <NewViewController: 0x5915f80> to <ImageViewController: 0x594a350>
while a transition is already in progress. Wait for viewDidAppear/viewDidDisappear
to know the current transition has completed'
How do I cure this? I have tried delays and other tricks but do not really understand how I'm supposed to use viewDidAppear or viewDidDisappear to help me. Also of note is that a very basic application with one view loading the picker then displaying another view with the image in does not produce the error. Any help gratefully received.
To address the specific issue described here, you could add the viewDidAppear method in your class:
-(void)viewDidAppear:(BOOL)animated
{
if (/*just visited ImagePicker*/)
{
ImageViewController *imageViewController = [[ImageViewController alloc] init];
imageViewController.delegate = self;
[self presentModalViewController:imageViewController animated:YES];
[imageViewController release];
}
}
Remove those lines from below your call:
[picker dismissModalViewControllerAnimated:YES];
So, whenever your class self appears (is displayed), it will call viewDidAppear... Since this most likely isn't really what you want all the time, you could add some variables to set/clear that defines whether or not to immediately present the imageViewController when self is displayed. Something like "If coming from image picker, show the imageViewController, otherwise do nothing".
That said, imho, pushing modal views is should generally be done in response to a user action and I would maybe rethink the user experience here - e.g. add a subview instead of pushing a modal view which you could do where your currently have the code - but if you're just playing around with some tutorials that should solve the NSInternalInconsistencyException. :) Cheers!
In iOS 5.0 and above you can use
[self dismissViewControllerAnimated:YES completion:^{
//present another modal view controller here
}];
I ran into this issue quite a few times. I recently started using this simple fix:
When I am going to present a new modal view controller immediately after dismissing another modal view controller, I simply dismiss the first one with argument NO in dismissModalViewControllerAnimated:.
Since the second view is presented with an animation, you hardly notice that the first one goes away fast. And you never get the transitions conflict.
I was having the same problem when i wanted to present an MFMailComposeViewController immediately after dismissing the UIImagePickerController. Heres what i did:
I removed the [imagePicker release]; statement from where i was presenting the image picker and put it in didFinishPickingMedia callback.
I used [self performSelector:#selector(presentMailComposer:) withObject:image afterDelay:1.0f];
Here's my code:
Displaying Image Picker
if([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]) {
NSArray *media = [UIImagePickerController availableMediaTypesForSourceType:UIImagePickerControllerSourceTypePhotoLibrary];
if ([media containsObject:(NSString*)kUTTypeImage] == YES) {
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
[picker setMediaTypes:[NSArray arrayWithObject:(NSString *)kUTTypeImage]];
picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
picker.delegate = self;
[self presentModalViewController:picker animated:YES];
//[picker release];
}
}
else {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Unavailable!"
message:#"Could not open the Photo Library."
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
[alert release];
}
Image Picker Delegate Callback - didFinishPickingMedia
NSString *mediaType = [info valueForKey:UIImagePickerControllerMediaType];
if([mediaType isEqualToString:(NSString*)kUTTypeImage]) {
UIImage *photoTaken = [info objectForKey:#"UIImagePickerControllerOriginalImage"];
//Save Photo to library only if it wasnt already saved i.e. its just been taken
if (picker.sourceType == UIImagePickerControllerSourceTypeCamera) {
UIImageWriteToSavedPhotosAlbum(photoTaken, self, #selector(image:didFinishSavingWithError:contextInfo:), nil);
}
//Pull up MFMailComposeView Controller
[self performSelector:#selector(composeMailWithPhoto:) withObject:photoTaken afterDelay:1.0f];
}
[picker dismissModalViewControllerAnimated:YES];
[picker release];
Display Mail Composer View
if ([MFMailComposeViewController canSendMail]) {
MFMailComposeViewController *mailPicker = [[MFMailComposeViewController alloc] init];
mailPicker.mailComposeDelegate = self;
// Fill out the email fields and Attach photograph to mail
static NSString *imageType = #"image/jpeg";
NSString *imageName = [NSString stringWithString:#"MyCoffeeCup.jpg"];
NSData *imageData = UIImageJPEGRepresentation(image, 1.0);
[mailPicker addAttachmentData:imageData mimeType:imageType fileName:imageName];
[mailPicker setToRecipients:[NSArray arrayWithObject:#"hello#xische.com"]];
[self presentModalViewController:mailPicker animated:YES];
//[self.navigationController pushViewController:mailPicker animated:YES];
[mailPicker release];
}
else {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Unavailable!"
message:#"This device cannot send emails."
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
[alert release];
}