MFMailComposeViewController few attachments - ios

I'm successfully sending an email with attached UIImage from my app, but is it possible to attach more than one image with MFMailComposeViewController ?

you can save all the images in an NSMutable array and run the code
[mailer addAttachmentData:imageData mimeType:#"image/png" fileName:#""];
for the count of your NSMutableArray. It will add the images to attachment field
for (int i = 0; i < [_textField0.emojiArray count]; i++)
{
emoji = [_textField0.emojiArray objectAtIndex:i];
UIImage *image = [EmojiResizer resizeImage2:[UIImage imageNamed:emoji.screenfilename]
imageData = [NSData dataWithData:UIImagePNGRepresentation(image)];
[mailViewController addAttachmentData:imageData mimeType:#"image/png" fileName:emoji.filename];
}
Do something like this.

Call addAttachment... for each attachment you wish to add.

Related

Receiveing array of Images from CoreData

I've created NSManagedObject* imagesArrayData that stores strings (paths) to images stored in the documents directory:
- (void)setImagesArray:(NSMutableArray *)imagesArray {
NSMutableArray* newImagesArray = [NSMutableArray new];
int i = 1;
for (UIImage* image in imagesArray) {
//generate path to createdFile
NSString* fileName = [NSString stringWithFormat:#"%#_%d", self.name, i];
NSString* filePath = [self documentsPathForFileName:fileName];
//save image to disk
NSData *imageData = UIImagePNGRepresentation(image);
[imageData writeToFile:filePath atomically:YES];
//add image path to CoreData
[newImagesArray addObject:filePath];
i++;
}
//set new value of imagesArray
imagesArrayData = [NSKeyedArchiver archivedDataWithRootObject:newImagesArray];
I am now not showing pathsToImages in header file, but property imagesArray:
-(NSMutableArray*) imagesArray {
NSMutableArray* images = [NSMutableArray new];
NSArray* imagePaths = [NSKeyedUnarchiver unarchiveObjectWithData:imagesArrayData];
for (NSString* imagePath in imagePaths) {
UIImage *image = [[UIImage alloc] initWithContentsOfFile: imagePath];
[images addObject:image];
}
return images;
The problem is, that whenever I want to get to [imagesArray objectatIndex:xxx], the imagesArray getter is called, and it takes time to recreate the full array. When trying to switch fast between images, the UI slows down.
What would be the elegant way to overcome this problem? Maybe creating another array full of images and updating it from time to time? Maybe something else? Please, help.
One thing you could do is refactor your getter to lazily load the array. If it is already defined, simply return it. If not, build it:
-(NSMutableArray*) imagesArray
{
if (!_imagesArray)
{
NSMutableArray* _imagesArray = [NSMutableArray new];
NSArray* imagePaths =
[NSKeyedUnarchiver unarchiveObjectWithData: imagesArrayData];
for (NSString* imagePath in imagePaths)
{
UIImage *image = [[UIImage alloc] initWithContentsOfFile: imagePath];
[_imagesArray addObject:image];
}
return _imagesArray;
}
I'm not sure what you mean about updating an array of images from time to time.
If your array of image names changes you will need some method to respond to those changes.

object inside NSMutableArray

I've a tableview which has list of images and image thumbnail (image list and thumbnails are parsed from JSON object), I'm adding image data objects to imagesArray like this -
ImageData *imageDataObject = [[ImageData alloc]initWithImageId:[[imageListArray
objectAtIndex:indexPath.row] imageId] imageData:imageData];
[imagesArray addObject:imageDataObject];
ImageData object
#property (nonatomic, strong) NSString* imageId;
#property (nonatomic, strong) NSData* imageData;
allImagesArray like this
[ImageData object1,ImageData object2,....]
I want to assign imageData of the object from this array based on selectedImageId to
UIImage* image =[[UIImage alloc] initWithData:........];
I'm not able to think of a way to get to that imageData based on selectedImageId
Please help.
Update -
Thank you all for the help, I could do it.
One of the possible way will be, iterate through the array, find your selectedImageId from the dictionary and use it.
Example:
ImageData *imageDataObject = nil;
for(int i=0; i<allImagesArray.count;i++){
NSDictionary *dict= allImagesArray[i];
imageDataObject = [dict objectForKey:selectedImageId];
if(imageDataObject != nil){
UIImage* image =[[UIImage alloc] initWithData:........];
//do whatever
break;
}
}
As per your EDIT:
What you have is an array of ImageData objects [ImageData1,ImageData2,...]. For each ImageData object, you have imageId and imageData property and what you want is simply compare the selectedImageId with this imageId and get the imageData from that.
So for that, in your PPImageViewController, you can iterate the allImagesArray like this and get the imageData.
for(ImageData* imgDataObj in self.allImagesArray){
if([imgDataObj.imageId isEqualToString:self.selectedImageId]){
UIImage* image =[[UIImage alloc] initWithData:imgDataObj.imageData];
}
}
So you have:
NSArray* allImagesArray = #[#{#"some_image_id_in_NSString_1":#"the data in NSData 1"}, #{#"some_image_id_in_NSString_2":#"the data in NSData 2"}];
As a property of PPImageViewController.
Assuming the imageid is an NSString and imagedata is NSData, you can create a method something like this on PPImageViewController:
- (UIImage*) findSelectedImage
{
UIImage* selectedImage;
for(NSDictionary* d in allImagesArray)
{
NSString* currentKey = [[d allKeys] objectAtIndex:0];
if([currentKey isEqualToString:[self selectedImageId]])
{
NSData* imageData = [d objectForKey:currentKey];
selectedImage = [UIImage imageWithData:imageData];
break;
}
}
return selectedImage;
}
Then call it like this, maybe on your viewDidLoad method:
UIImage* selectedImage = [self findSelectedImage];
Hope it help.
I see you are adding ImageData objects directly into the Array. You could have just used a NSDictionary instead. The key can be imageID (assuming it to be unique) and value will be the imageData object. Then pass the dictionary instead of array to PPImageViewController.
NSMutableDictionary *imageData = [NSMutableDictionary dictionary];
ImageData *imageDataObject = [[ImageData alloc]initWithImageId:[[imageListArray
objectAtIndex:indexPath.row] imageId] imageData:imageData];
[imageData setObject:imageDataObject forKey:imageId];
And then within PPImageViewController, you can easily get the imageDataObject based on selected imageID like this:
ImageData *imageDataObject = allImagesDictionary[selectedImageID];
EDIT:
NSArray *imageIndexes = [allImagesDictionary allKeys];
// Now use imageIndexes to populate your table. This will guarantee the order
// Fetch the imageId
selectedImageID = imageIndexes[indexPath.row];
// Fetch the imageData
ImageData *imageDataObject = allImagesDictionary[selectedImageID];

Send a UIImage through an email

Given that I have a UIImage that is stored in a local variable:
UIImage *myImage = (Some image extracted somewhere)
How do I add this image as an attachment through MFMailComposeViewController ?
The image isn't stored on the users device and it's simply available at runtime.
So I can't access this image through a file name as other questions/examples have demonstrated.
Thank you!
NSData *imageData = UIImageJPEGRepresentation(photo, 0.9);
NSString *attachmentName = #"Any name.jpg"
[mailer addAttachmentData:imageData mimeType:#"image/jpeg" fileName:attachmentName];

Iterating an NSMutableDictionary with UIImage not working

I am trying to add Images fetched from an external service to an NSMutableDictionary and seeing weird results. This is what I am doing:
- (void)fetchImages{
//Fetch Item Brand Images
//self.itemBrands is an NSArray of NSDictionaries
for (NSDictionary *itemBrand in self.itemBrands){
NSString *currentItemId = [itemBrand objectForKey:#"ITEM_ID"];
//Valid Item Id. This Log message is displayed
NSLog(#"Current Item Id: %#",currentItemId);
NSString *currentItemImageUrl = [[IMAGE_URL stringByAppendingString:currentItemId] stringByAppendingString:#".png"];
//Image URL is valid. This log message is displayed
NSLog(#"Current Image URL: %#",currentItemImageUrl);
NSURL *url = [NSURL URLWithString:currentItemImageUrl];
NSData *data = [NSData dataWithContentsOfURL:url];
UIImage *image = [UIImage imageWithData:data];
if (image == nil){
//This log message is displayed when image is not present
NSLog(#"Image not Present 1");
}else{
//This log message is displayed when image is present
NSLog(#"Image Present 1");
[self.itemBrandImages setObject:image forKey:currentItemId];
}
}
//This for loop is not being executed at all. No log messages displayed.
for(id key in self.itemBrandImages){
NSLog(#"Current Item Id2: %#",key);
if ([self.itemBrandImages objectForKey:key] == nil){
NSLog(#"Image Not Present 2");
}else{
NSLog(#"Image Present 2");
}
}
}
The 2nd for loop where I am iterating over self.itemBrandImages is not being executed at all. None of the log messages inside are being displayed.
I tried the following before posting my issue here:
1) Researched similar problems in stack overflow and incorporated suggestion from one of them. The suggestion was "Perform an alloc init of the NSMUtableDictionary" in the init method of the .m file. This didn't help either.
2) To isolate the issue, I even tried adding a simple string to the NSMUtableDictionary instead of the image but even that does not seem to retained.
I am really confused as as to what I am missing or doing wrong here. Inputs are really appreciated.
Thanks,
Mike G
Perhaps:
for(NSString *key in [self.itemBrandImages allKeys])
I did an alloc init of the NSMutableDictianary right in my fetchImages method and it worked! Not sure why the alloc init in the init method did not work.
So here are my takeaways from this issue:
1) If you have an Array or dictionary #property that you are just getting and setting and not really adding or deleting objects to, then you don't need to explicitly alloc init them.
2) If you have an Array or dictionary #property that you are adding or deleting objects to ,you need to explicitly alloc init them.
Are my above statements true? Would love to hear your inputs on this.
Thanks,
Mike
New code:
- (void)fetchImages{
//Fetch Item Brand Images
self.itemBrandImages = [[NSMutableDictionary alloc] init];
for (NSDictionary *itemBrand in self.itemBrands){
NSString *currentItemId = [itemBrand objectForKey:#"ITEM_ID"];
NSLog(#"Current Item Id in ItemList: %#",currentItemId);
NSString *currentItemImageUrl = [[#"http://anythingtogo.freeiz.com/images/"stringByAppendingString:currentItemId] stringByAppendingString:#".png"];
NSLog(#"Current Image URL in ItemList: %#",currentItemImageUrl);
NSURL *url = [NSURL URLWithString:currentItemImageUrl];
NSData *data = [NSData dataWithContentsOfURL:url];
UIImage *image = [UIImage imageWithData:data];
if (image == nil){
NSLog(#"Image not Present 1");
}else{
NSLog(#"Image Present 1");
[self.itemBrandImages setObject:#"Test" forKey:currentItemId];
}
}

Fighting with images in E-mail

My App sends an e-mail with images but there is no images in the e-mail.
I create a HTML string and send that as the body in the e-mail. But there is nothing in the e-mail when doing it on the device.
In the simulator is okay.
I put a WebView in my App and put the HTML in and its shows all the images.
Anyone know what could be the issue?
This is code I used to attach image in mail body
NSMutableString *htmlBody = [[NSMutableString alloc] initWithString:#"<html><body>"];
[htmlBody appendString:#"<p>Enter Text Here</p>"];
UIImage *emailImage = [UIImage imageNamed:#"image.png"];
NSData *imageData = [NSData dataWithData:UIImagePNGRepresentation(emailImage)];
NSString *base64String = [imageData base64EncodedString];
[htmlBody appendString:[NSString stringWithFormat:#"<p><b><img src='data:image/png;base64,%#'> </b></p>",base64String]];
[htmlBody appendString:#"</body></html>"];
NSLog(#"%#",htmlBody);
[mailComposer htmlBody isHTML:YES];
Hope it helps you..

Resources