I have simple text file generated in my application. The thing is I want to upload this text file on iCloud so that if the user installs app and inputs data he desires and then agin uninstalls this app. Then the next time he installs that app again I want to fetch the text file uploaded the first time he had used the same app.
I am facing a huge problem in integrating iCloud to my app.
I have done much research but didn't got any specific answers.
P.S. = I am not using Core data.
All i want is to upload the text file generated by the app into the iCloud Drive.
Please guide me step by step how can I achieve this. I have my developer account and I have a bit knowledge about the certificates and all. But still if anyone can please guide me how to achieve it.
I JUST WANT TO UPLOAD THE TEXT FILE TO ICLOUD AND RETRIEVE IT AGAIN WHEN THE SAME APP IS INSTALLED AGAIN (EVEN IF THE APP IS GETTING INSTALLED ON OTHER DEVICES).
ViewController.m
#pragma mark - Image Pick
- (IBAction)pickImage:(id)sender {
//select an image
UIImagePickerController *picker = [[UIImagePickerController alloc]init];
picker.delegate = self;
[self presentViewController:picker animated:YES completion:nil];
}
-(void)imagePickerControllerDidCancel:(UIImagePickerController *)picker
{
[self dismissViewControllerAnimated:YES completion:nil];
}
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info
{
[self dismissViewControllerAnimated:YES completion:nil];
UIImage* image = [info objectForKey:UIImagePickerControllerOriginalImage];
self.imageView.image = image;
//SAVE IMAGE IN iCloud
AppDelegate* myAppDelegate = (AppDelegate*)[UIApplication sharedApplication].delegate;
NSURL* cloudeImage = [myAppDelegate applicationCloudFolder:#"thePicture"];
NSData* imageDate = UIImagePNGRepresentation(image);
[imageDate writeToURL:cloudeImage atomically:YES];
}
-(void)populateUI
{
AppDelegate* myAppDelegate = (AppDelegate*)[UIApplication sharedApplication].delegate;
NSURL* cloudeImageURL = [myAppDelegate applicationCloudFolder:#"thePicture"];
NSData* imageDate = [NSData dataWithContentsOfURL:cloudeImageURL];
UIImage* image = [UIImage imageWithData:imageDate];
if (image) {
self.imageView.image = image;
}
else
{
//download image from iCloud
NSLog(#"Downloading Image...");
[[NSFileManager defaultManager]startDownloadingUbiquitousItemAtURL:cloudeImageURL error:nil];
}
}
- (NSMetadataQuery *)query {
if (!_query) {
_query = [[NSMetadataQuery alloc]init];
NSArray *scopes = #[NSMetadataQueryUbiquitousDocumentsScope];
_query.searchScopes = scopes;
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"%K like %#", NSMetadataItemFSNameKey, #"*"];
_query.predicate = predicate;
if (![_query startQuery]) {
NSLog(#"Query didn't start... for whatever reason");
}
}
return _query;
}
AppDelegate.m
-(NSURL*)applicationCloudFolder:(NSString*)fileName
{
//TEAM ID AND CONTAINER ID
NSString* teamID = #"V58ESG9PLE";
NSString* bundelID =[NSBundle mainBundle].bundleIdentifier;
NSString* containerID = [NSString stringWithFormat:#"%#.%#",teamID,bundelID];
// URL to Cloud Folder
NSURL* cloudeRootURL = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:containerID];
NSLog(#"cloudeRootURL %#",cloudeRootURL);
NSURL* cloudDocuments = [cloudeRootURL URLByAppendingPathComponent:#"Document"];
//Apend our file name
cloudDocuments = [cloudDocuments URLByAppendingPathComponent:fileName];
return cloudDocuments;
}
Now I am not getting is my data being saved? ,Where is it getting saved? how can I retrieve it?
P.S. I am saving a picture
Related
I have a camera application where the user can share the photos taken through email.
I am using MFMailComposerViewController to send mail. Here is the piece of code.
- (void) contactEmailRecepients:(NSArray *)emailIDs
subject:(NSString *)subject
attachment:(NSMutableDictionary *)attachmentDictionary
sender:(UIViewController *)sender
{
if ([MFMailComposeViewController canSendMail])
{
mailViewController = [[MFMailComposeViewController alloc] init];
mailViewController.mailComposeDelegate = self;
[mailViewController setToRecipients:emailIDs];
[mailViewController setSubject:subject];
NSData *attachmentData = [attachmentDictionary objectForKey:#"attachmentData"];
if (nil != attachmentData)
{
[mailViewController addAttachmentData:attachmentData
mimeType:[attachmentDictionary objectForKey:#"mimeType"]
fileName:[attachmentDictionary objectForKey:#"fileName"]];
}
[sender presentViewController:mailViewController
animated:YES
completion:^{}];
attachmentData = nil;
[attachmentDictionary removeAllObjects];
attachmentDictionary = nil;
}
else
{
// display error message
}
}
My problem is every time I send a mail through my application the VM(Virtual Memory) increases by 6/7 MB. But this does not happen if I comment out following part.
if (nil != attachmentData)
{
[mailViewController addAttachmentData:attachmentData
mimeType:[attachmentDictionary objectForKey:#"mimeType"]
fileName:[attachmentDictionary objectForKey:#"fileName"]];
}
The increased VM is due to CGRasterDataand the responsible library is CoreGraphicsand responsible caller is CGDataProvideCreateWithCopyOfDatawhen I check it through Xcode 5.0.2 instruments.So somewhere a copy is getting created which is not getting released later.I am suspecting the memory allocated to display the image in Email UIActionSheetis not getting released.
Any help is appreciated.
EDIT:
Adding the piece of code where attachmentData is getting initialized.
- (void)postPhotoFromPath:(NSString *)filePath
sender:(UIViewController *)sender
{
NSData *photoData = [NSData dataWithContentsOfFile:filePath];
if (nil == photoData)
{
//display error message
}
else
{
NSString *fileName = [[filePath componentsSeparatedByString:#"/"] lastObject];
[self contactEmailRecepients:nil
subject:nil
attachment:[NSDictionary dictionaryWithObjectsAndKeys:
photoData, #"attachmentData",
#"image/jpeg", #"mimeType",
fileName, #"fileName",
nil]
sender:sender];
}
}
Also I noticed carefully that VM increases exactly when i get the UIActionSheetregarding which image size to send(whether to send the original size or downscaled size). I am attaching the screenshot for the same here.
I am working on an iOS app and I recently implemented a imagePicker in a popover that allows a user to record photos and videos. I would like to store these in the iPad's photo roll so that the user can sync them in iTunes later. I've been able to do this successfully, but I would like to give each photo and video a unique name that contains useful information about the photo and video so I can load them later. Specifically, I would like to store the photo using a property of the class, live_trial_id, as the filename. Below is the code that I am currently using to store my photos and videos to the photo roll. I understand that I could do this with metadata for pictures, but for the videos I am lost. Thanks in advance for any help with this issue!
-(void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info{
NSString *mediaType = [info objectForKey:UIImagePickerControllerMediaType];
UIImage *originalImage, *editedImage, *imageToSave;
// Handle a still image capture
if( [mediaType isEqualToString:#"public.image"]){
editedImage = (UIImage *) [info objectForKey:
UIImagePickerControllerEditedImage];
originalImage = (UIImage *) [info objectForKey:
UIImagePickerControllerOriginalImage];
if (editedImage) {
imageToSave = editedImage;
} else {
imageToSave = originalImage;
}
// Get the image metadata
UIImagePickerControllerSourceType pickerType = picker.sourceType;
if(pickerType == UIImagePickerControllerSourceTypeCamera)
{
NSDictionary *imageMetadata = [info objectForKey:
UIImagePickerControllerMediaMetadata];
// Get the assets library
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
ALAssetsLibraryWriteImageCompletionBlock imageWriteCompletionBlock =
^(NSURL *newURL, NSError *error) {
if (error) {
NSLog( #"Error writing image with metadata to Photo Library: %#", error );
} else {
NSLog( #"Wrote image with metadata to Photo Library");
}
};
// Save the new image (original or edited) to the Camera Roll
[library writeImageToSavedPhotosAlbum:[imageToSave CGImage]
metadata:imageMetadata
completionBlock:imageWriteCompletionBlock];
}
}
if ([mediaType isEqualToString:#"public.movie"]) {
UIImagePickerControllerSourceType pickerType = picker.sourceType;
if(pickerType == UIImagePickerControllerSourceTypeCamera)
{
NSURL *mediaURL = [info objectForKey:UIImagePickerControllerMediaURL];
// Get the assets library
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
ALAssetsLibraryWriteVideoCompletionBlock videoWriteCompletionBlock =
^(NSURL *newURL, NSError *error) {
if (error) {
NSLog( #"Error writing image with metadata to Photo Library: %#", error );
} else {
NSLog( #"Wrote image with metadata to Photo Library");
}
};
// Save the new image (original or edited) to the Camera Roll
[library writeVideoAtPathToSavedPhotosAlbum:mediaURL
completionBlock:videoWriteCompletionBlock];
}
}
I would also like to avoid creating a custom library or custom metadata if at all possible. I really just wanted to change the filename on the way to the photo roll
I ended up answering my own question. What I wanted to do was to save to the application's documents directory instead of the photo roll. This allowed me to access the files that I had saved and also to sync them to the computer when attached later.
With this code below, I can extract metadata from an image (pre-added to my project), and render the info as text. This is exactly what I want to do. The SYMetadata is created by pointing to an image via URL. initWithAbsolutePathURL. I want to do the same thing with a UIImage or maybe the image that is being loaded to the UIImage. How do I get the URL to the image that the picker selects? Or how do I create an "asset" from this incoming image?
The documentation describes initWithAsset. Have not figured out how to use it yet though, or if this is the right way to go for my purpose. Any help greatly appreciated.
NSURL *imageURL = [[NSBundle mainBundle] URLForResource:#"someImage" withExtension:#"jpg"];
SYMetadata *metadata = [[SYMetadata alloc] initWithAbsolutePathURL:imageURL];
[textView setText:[[metadata allMetadatas] description]];
Note: I tried adding an NSURL like this imageURL = [info valueForKey:#"UIImagePickerControllerReferenceURL"];, in the "pickerDidFinish" method but the metadata is null after I add this URL to the above code.
If you are using the imagePickerController, the delegate method will give you what you need
- (void) imagePickerController:(UIImagePickerController *)picker
didFinishPickingMediaWithInfo:(NSDictionary *)info
{
if ([[info allKeys] containsObject:UIImagePickerControllerReferenceURL]){
// you will get this key if your image comes from a library
[self setMetaDataFromAssetLibrary:info];
} else if ([[info allKeys] containsObject:UIImagePickerControllerMediaMetadata]){
// if the image comes from the camera you get the metadata in it's own key
self.rawMetaData = [self metaDataFromCamera:info];
}
}
From Asset Library - bear in mind that it takes time to complete and has an asynchronous completion block, so you might want to add a completion flag to ensure you don't access the property before it has been updated.
- (void) setMetaDataFromAssetLibrary:(NSDictionary*)info
{
NSURL *assetURL = [info objectForKey:UIImagePickerControllerReferenceURL];
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
[library assetForURL:assetURL
resultBlock:^(ALAsset *asset) {
self.rawMetaData = asset.defaultRepresentation.metadata;
}
failureBlock:^(NSError *error) {
NSLog (#"error %#",error);
}];
}
From Camera:
- (NSDictionary*)metaDataFromCamera:(NSDictionary*)info
{
NSMutableDictionary *imageMetadata = [info objectForKey:UIImagePickerControllerMediaMetadata];
return imageMetadata;
}
Here is how to get metadata from a UIImage
- (NSDictionary*)metaDataFromImage:(UIImage*)image
{
NSData *jpegData = [NSData dataWithData:UIImageJPEGRepresentation(image, 1.0)];
return [self metaDataFromData:jpegData];
}
But take care - a UIImage can already stripped of much of the metadata from the original.. you will be better off getting the metadata from the NSData that was used to create the UIImage...
- (NSDictionary*)metaDataFromData:(NSData*)data
{
CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef)data, NULL);
CFDictionaryRef imageMetaData = CGImageSourceCopyPropertiesAtIndex(source,0,NULL);
return (__bridge NSDictionary *)(imageMetaData);
}
If you've an ALAsset (in my sample _detailItem), you can have metadata in this way:
NSDictionary *myMetadata = [[_detailItem defaultRepresentation] metadata];
I'm facing a strange issue in my app and I need your help !
I am using a MFMailComposeViewController to send emails with attachment data. The attachment is either a PDF, a CSV or a XLS file. A ZIP file can also be added to the mail.
Everything works fine in most cases but sometimes (actually quite often), when the attachment is a XLS and a ZIP is added, I receive multiple memory warnings and the composer returns MFMailComposeResultFailed, with an error that doesn't help at all (only saying code error 1, "The operation couldn’t be completed. (MFMailComposeErrorDomain error 1.)").
My question is why does it do that ? I assume the memory warnings are telling me something is not well managed but I can't figure out what...
Here is my code for sending the email
-(void) sendMail {
MFMailComposeViewController *picker = [[MFMailComposeViewController alloc] init];
[self prepareMailPicker:picker];
NSString *filePath = [self getFilePath:pType];
NSString *zipFile = [self getZipPath];
NSString *mimeType;
int userPhoto = [User getCSVPhoto];
switch (pType) {
case EPDF:
mimeType = #"application/pdf";
userPhoto = [User getPDFPhoto];
break;
case ECSV:
mimeType = #"text/csv";
break;
case EExcel:
mimeType = #"application/vnd.ms-excel";
break;
default:
break;
}
NSData *attachmentData = [NSData dataWithContentsOfFile:filePath];
[picker addAttachmentData:attachmentData mimeType:mimeType fileName:[filePath lastPathComponent]];
if (userPhoto == 1 && shouldAddZip) {
NSData *zipData = [NSData dataWithContentsOfFile:zipFile];
[picker addAttachmentData:zipData mimeType:#"application/zip" fileName:[zipFile lastPathComponent]];
}
shouldAddZip = NO;
[self presentModalViewController:picker animated:YES];
}
-(void) prepareMailPicker:(MFMailComposeViewController*)picker {
picker.mailComposeDelegate = (id<MFMailComposeViewControllerDelegate>)self;
picker.navigationBar.tintColor = grayDark;
[picker setSubject:[TextManager textForKey:#"EMAIL_SUBJECT"]];
NSString *email = [[User currentUser] getEmail];
if (email && ![email isEqualToString:#""])
[picker setToRecipients:[NSArray arrayWithObject:email]];
NSString *emailBody = [TextManager textForKey:#"EMAIL_TEXT"];
[picker setMessageBody:emailBody isHTML:YES];
}
Any help would be grately apreciated !
EDIT: as asked by #matt, here is a log to prove that nothing is set to nil :
filePath : /var/mobile/Applications/A57F5CD2-E3FE-4417-8810-D746A22CF434/Documents/iNdF_Export_2012-11-19.xls
zipFile : /var/mobile/Applications/A57F5CD2-E3FE-4417-8810-D746A22CF434/Documents/iNdF_recus_2012-11-19.zip
attachmentData : (NSConcreteData *) <0x1d9c3c20> 53 874 bytes
zipData : (NSConcreteData *) <0x1f989100> 6 838 456 bytes
as you say, the problem seems most probably to do with memory management, given the memory warnings you are receiving.
your code is retaining a reference count to the attachmentData from the first file even as it goes out to get the zipData for the second file. internally, the picker is probably copying that data …
so the more you can do to release your references to large data as early as possible, the more likely you are not to get the memory warnings.
and if the problem is that the picker is unable to finish the attachment due to running out of memory, and you are able to get through it by doing early release, then breaking up the code in the following way may help you.
- (void)sendMailPicker:(MFMailComposeViewController*)picker addAttachmentUsingMimeType:(NSString*)mimeType {
NSString *filePath = [self getFilePath:pType];
NSData *attachmentData = [NSData dataWithContentsOfFile:filePath];
[picker addAttachmentData:attachmentData mimeType:mimeType fileName:[filePath lastPathComponent]];
}
- (void)sendMailAddPhotoUsingPicker:(MFMailComposeViewController*)picker {
NSString *zipFile = [self getZipPath];
NSData *zipData = [NSData dataWithContentsOfFile:zipFile];
[picker addAttachmentData:zipData mimeType:#"application/zip" fileName:[zipFile lastPathComponent]];
}
- (void)sendMail {
MFMailComposeViewController *picker = [[MFMailComposeViewController alloc] init];
[self prepareMailPicker:picker];
NSString *mimeType;
int userPhoto = [User getCSVPhoto];
switch (pType) {
case EPDF:
mimeType = #"application/pdf";
userPhoto = [User getPDFPhoto];
break;
case ECSV:
mimeType = #"text/csv";
break;
case EExcel:
mimeType = #"application/vnd.ms-excel";
break;
default:
break;
}
[self sendMailPicker:picker addAttachmentUsingMimeType:mimeType];
if (userPhoto == 1 && shouldAddZip) {
[self sendMailAddPhotoUsingPicker:picker];
}
shouldAddZip = NO;
[self presentModalViewController:picker animated:YES];
}
I guess that the problem is related to memory, when you create NSData you create in the heap. If it is to big you'll start to receive memory warnings. One way to avoid memory could be create a memory mapped NSData or an an NSStream but I have no idea on how to integrate a NSStream in mail composer. Which is the average size of your attachment?
You can also try to profile your app with Allocations to see wich is the memory footprint of your app, maybe is already too high.
like the some problems i had faced before.
1. Please check, there is internet availability using "Reachability" class file.
2. Please check your data size is within the limit.
3. Please check you configured your email id with your device.
you can also call [yourobj cansendmail] function to check whether it can send mail or not.
I'm working on an iphone app that uses Abbyy OCR.
Using the wrapper class for iphone there is a method :
[ocrManager recognizeImage:[choosenImage image] withCallback:self];
a UIImage is passed as a parameter which is used to recognize characters. But every time i receive exception "Required Data File Missed".
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
[picker dismissModalViewControllerAnimated:YES];
[[UIApplication sharedApplication] setStatusBarHidden:NO];
if(check == 1)
{
return;
}
check = 1;
UIImage *image = [info objectForKey:#"UIImagePickerControllerOriginalImage"];
[choosenImage setImage:image];
[process setHidden:NO];
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"license" ofType:#""];
NSData *license = [[NSData alloc] initWithContentsOfFile:filePath];
CMocrManager *ocrManager = [CMocrManager createManager:license];
NSSet *languages = [[NSSet alloc] initWithArray:[NSArray arrayWithObject:#"English"]];
[ocrManager setLanguages:languages];
[ocrManager setDefaultImageResolution:0];
#try {
[ocrManager recognizeImage:[choosenImage image] withCallback:self];
}
#catch (NSException *exception) {
NSString *ex = exception.reason;
}
CMocrLayout* recognitionResult = [ocrManager copyRecognitionResults];
NSArray* strings = [recognitionResult copyStrings];
}
the image can be seen on UIImageView but when I pass it to recognizeImage method it throws the exception.
I've been researching a lot but unable to find a solution. Any help is appreciated.
My name is Nikolay Khlebinsky, i work # ABBYY.
"Required Data File Missed" error message is displayed when resource files are missing (keywords, patterns or dictionaries). Refer to «How to Work with the ABBYY Mobile OCR Engine Library on the iPhone» help article for project organization guide. You can also look for iPhone project sample in the engine distributive.
If you would still experience any difficulties, please visit our technical support contacts page at http://www.abbyy.com/support/contacts/ Choose your country and your product, hit 'Search' and you'll get contacts of the proper ABBYY representatives. Contacting them is the fastest way to solve technical issues.