I am generating a pdf from html and attaching to email. The problem I have is the pdf is attaching to the email before it has finished generating.
I have tried using a completion block but without success.
#property (nonatomic, strong) void(^completionHandler)(BOOL);
[self generatePDF:html andCompletionHandler:^(BOOL result) {
// COMPLETED ? - ATTACH the file
NSString *docDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *pdfPathFile=[docDir stringByAppendingString:#"/report.pdf"];
NSData *pdfData = [NSData dataWithContentsOfFile:pdfPathFile];
[controller setMessageBody:#"report attached" isHTML:NO];
[controller addAttachmentData:pdfData mimeType:#"application/pdf" fileName:#"report.pdf"];
NSLog(#"attaching pdf with length %d",[pdfData length]);
}];
-(void)generatePDF:(NSMutableString*)HtmlString andCompletionHandler:(void (^)(BOOL result))handler{
_completionHandler = handler;
NSString *docDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *pdfPathFile=[docDir stringByAppendingString:#"/report.pdf"];
NSFileManager *fm = [NSFileManager defaultManager];
NSError *error;
if ([fm fileExistsAtPath:pdfPathFile] == YES){
[fm removeItemAtPath:pdfPathFile error:&error];
}
//I am using NDHTMLtoPDF to create the PDF
self.PDFCreator = [NDHTMLtoPDF createPDFWithHTML:HtmlString pathForPDF:pdfPathFile delegate:self pageSize:kPaperSizeA4 margins:UIEdgeInsetsMake(10,5,10,5)];
}
#pragma mark NDHTMLtoPDFDelegate
- (void)HTMLtoPDFDidSucceed:(NDHTMLtoPDF*)htmlToPDF
{
NSString *result = [NSString stringWithFormat:#"HTMLtoPDF did succeed - %#", htmlToPDF.PDFpath];
NSLog(#"%#",result);
_completionHandler(YES);
}
Related
I am trying to attach a video to an email. It is not a local video so I write it to a file. Then I get the data from that file and attach to the email. When the email comes up, the only thing there is the file name "video.mp4" with no video.
MFMailComposeViewController *controller = [[MFMailComposeViewController alloc] init];
controller.mailComposeDelegate = self;
NSData *videoData = [NSData dataWithContentsOfURL:url];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *tempPath = [documentsDirectory stringByAppendingFormat:#"/video.mp4"];
NSLog(#"writing");
BOOL success = [videoData writeToFile:tempPath atomically:NO];
if (success){
NSError *error = nil;
NSData *data = [NSData dataWithContentsOfFile:tempPath];
NSLog(#"path: %#", tempPath);
if (error) {
NSLog(#"%#", [error localizedDescription]);
}else{
[controller addAttachmentData:data mimeType:#"video/mp4" fileName:#"video.mp4"];
NSLog(#"Data has loaded successfully.");
}
}
I think only approach to try is formatting mail as HTML. Otherwise you will always sending an attachment.
NSString *messageBody = #" /*Some HTML format containing HTML5 video player*/";
[controller setMessageBody:messageBody isHTML:YES];
So you need to look for suitable CSS and HTML tags for your video. But don't forget to test it with most e-mail clients as you may see different looks.
I want to store .zip files on iCloud. Anybody help me how to upload and restore? I have read the Apple guideline for iCloud backup and now I have created one folder with some files and two folders with multiple images and then generate zip file of that folder.
First Save your File and Folder on Local Storage.
Then Create this File & Folder's Zip File.
And Last Upload Your zip file on iCloud.
For get this file doing reverse process.
- (void)viewDidLoad {
[super viewDidLoad];
[self CreatFileAndFolder];
}
Create Folder on local and save file in this folder that you want upload on iCloud Drive.
-(void)CreatFileAndFolder{
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0]; // Get documents folder
NSString *dataPath = [documentsDirectory stringByAppendingPathComponent:#"/meetInChat"];
if (![[NSFileManager defaultManager] fileExistsAtPath:dataPath])
[[NSFileManager defaultManager] createDirectoryAtPath:dataPath withIntermediateDirectories:NO attributes:nil error:&error];
NSString *stringToWrite = #"1\n2\n3\n41\n2\n3\n41\n2\n3\n41\n2\n3\n41\n2\n3\n41\n2\n3\n41\n2\n3\n41\n2\n3\n41\n2\n3\n41\n2\n3\n41\n2\n3\n41\n2\n3\n41\n2\n3\n41\n2\n3\n41\n2\n3\n41\n2\n3\n4";
NSString *exportPath = [dataPath stringByAppendingString:#"/mytext.txt"];
[stringToWrite writeToFile:exportPath atomically:YES encoding:NSUTF8StringEncoding error:&error];
}
Create Action that First Create Zip file your Folder and then Upload your Zip file on iCloud Drive.
-(IBAction) iCloudSyncing:(id)sender
{
[self zipFolder];
//--------------------------Zip Folder Upload on iCloud-----------------------------//
NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *zipFilePath = [documentsDirectory stringByAppendingPathComponent:#"meetInChat.zip"];
NSLog(#"FilePath=>%#",zipFilePath);
NSURL *u = [[NSURL alloc] initFileURLWithPath:zipFilePath];
NSData *data = [[NSData alloc] initWithContentsOfURL:u];
NSURL *ubiq = [[NSFileManager defaultManager]URLForUbiquityContainerIdentifier:nil];
NSURL *ubiquitousPackage = [[ubiq URLByAppendingPathComponent:#"Documents"]URLByAppendingPathComponent:#"meetInChat.zip"];
Mydoc = [[MyDocument alloc] initWithFileURL:ubiquitousPackage];
Mydoc.zipDataContent = data;
[Mydoc saveToURL:[Mydoc fileURL] forSaveOperation:UIDocumentSaveForCreating completionHandler:^(BOOL success)
{
if (success)
{
NSLog(#"PictureZip: Synced with icloud");
[[NSUbiquitousKeyValueStore defaultStore]setData:data forKey:#"meetInChat"];
}
else
NSLog(#"PictureZip: Syncing FAILED with icloud");
}];
}
Create Zip file from your folder
-(BOOL)zipFolder
{
//--------------------------Create Zip Folder -----------------------------//
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docDirectory = [paths objectAtIndex:0];
BOOL isDir=NO;
NSArray *subpaths = nil;
NSString *exportPath = [docDirectory stringByAppendingString:#"/meetInChat"];
NSFileManager *fileManager = [NSFileManager defaultManager];
if ([fileManager fileExistsAtPath:exportPath isDirectory:&isDir] && isDir){
subpaths = [fileManager subpathsAtPath:exportPath];
}
NSString *meetInChatPath = [docDirectory stringByAppendingString:[NSString stringWithFormat:#"/%#.zip",#"meetInChat"]];
ZipArchive *archiver = [[ZipArchive alloc] init];
[archiver CreateZipFile2:meetInChatPath];
if (isDir) {
for(NSString *path in subpaths){
NSString *fullPath = [exportPath stringByAppendingPathComponent:path];
if([fileManager fileExistsAtPath:fullPath isDirectory:&isDir] && !isDir){
[archiver addFileToZip:fullPath newname:path];
}
}
} else {
[archiver addFileToZip:exportPath newname:#"meetInChat"];
}
BOOL successCompressing = [archiver CloseZipFile2];
if(successCompressing)
return YES;
else
return NO;
}
Here Get ZipFile back From iCloud Drive then Doing reverse process Unzip your file and get data back.
- (IBAction)GetData:(id)sender {
//--------------------------Get data back from iCloud -----------------------------//
id token = [[NSFileManager defaultManager] ubiquityIdentityToken];
if (token == nil)
{
NSLog(#"ICloud Is not LogIn");
}
else
{
NSLog(#"ICloud Is LogIn");
NSData *dataFile = [[NSUbiquitousKeyValueStore defaultStore]dataForKey:#"meetInChat"];
NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString* fileName = [NSString stringWithFormat:#"meetInChat.zip"];
NSString* fileAtPath = [documentsDirectory stringByAppendingPathComponent:fileName];
[dataFile writeToFile:fileAtPath atomically:NO];
}
}
I have files download at didFinishDownloadingToURL: and I want to unzip it. My current code looks like this:
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location
{
for(NSMutableDictionary *downloadInfo in downloadingArray)
{
if([[downloadInfo objectForKey:kMZDownloadKeyTask] isEqual:downloadTask])
{
if (location)
{
NSString *srcPath = location.absoluteString;
NSString *fullPathDst = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
//unzip
ZipArchive *zipArchive = [[ZipArchive alloc] init];
[zipArchive UnzipOpenFile:srcPath Password:#"pasword"];
[zipArchive UnzipFileTo:fullPathDst overWrite:YES];
[zipArchive UnzipCloseFile];
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
NSArray *files = [fileManager contentsOfDirectoryAtPath:fullPathDst error:&error];
NSLog(#"files: %#", files);
}
break;
}
}
}
the files array is empty. What am I doing wrong?
You shouldn't use absoluteString, as that includes a scheme (e.g. file://). Use path method, instead.
You have not written the file name and file type :-
NSString *filepath = [[NSBundle mainBundle] pathForResource:#"ZipFileName" ofType:#"zip"];
The unzipping would create a folder in documents directory which would contain the files. Please check that
NSString *zipPath = [[NSBundle mainBundle] pathForResource:zipFileName ofType:#"zip"];
NSString *destinationPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
[SSZipArchive unzipFileAtPath:zipPath toDestination:destinationPath];
Get zip file from documents directory:-
NSString *filename = #"MyZipFile.zip";
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString * zipPath = [documentsDirectory stringByAppendingPathComponent:filename];
NSString *destinationPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
[SSZipArchive unzipFileAtPath:zipPath toDestination:destinationPath];
I am saving a file like this in my iOS App in my UIImagePickerDelegate's method didFinishPIckingMediaWithInfo:
// write
NSString* filePath = [NSHomeDirectory() stringByAppendingPathComponent:[NSString stringWithFormat:#"Documents/invoice.jpeg"]];
NSData *imageData = UIImageJPEGRepresentation(info[UIImagePickerControllerOriginalImage], 0.0);
if (imageData != nil) {
[imageData writeToFile:filePath atomically:YES];
}
Then I am retrieving the file like this:
// load
NSString *searchFilename = #"invoice.jpeg";
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSDirectoryEnumerator *direnum = [[NSFileManager defaultManager] enumeratorAtPath:documentsDirectory];
NSString *documentsSubpath;
while (documentsSubpath = [direnum nextObject])
{
if (![documentsSubpath.lastPathComponent isEqual:searchFilename]) {
continue;
}
NSURL *fileURL = [[NSURL alloc]initFileURLWithPath:[NSString stringWithFormat:#"%#/%#",documentsDirectory,documentsSubpath]];
[self.imageContentView setupImageViewerWithImageURL:fileURL onOpen:^{
NSLog(#"open %#",fileURL);
} onClose:^{
NSLog(#"close %#",fileURL);
}];
}
The files do get loaded properly. However, when I update the photo (imageData) in my UIImagePickerDelegate and try to reload the image, I still get the original image written into my app documents.
I have a CSV file that I'm downloading from an S3 account and I would like to show it in my ios app by using the Quicklook framework.
The error I'm getting is in my console. It says
QLPreviewController's datasource shouldn't be nil at this point.
This appears after this line of code runs // Set data source
[previewer setDataSource:self];
here's all the code for downloading the file, saving it and then loading with quicklook
-(void)showDocument
{
NSString *stringURL = #"http://jornada.s3.amazonaws.com/Dust.csv";
NSURL *url = [NSURL URLWithString:stringURL];
NSData *urlData = [NSData dataWithContentsOfURL:url options:NSDataReadingUncached error:nil];
if ( urlData )
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *filePath = [NSString stringWithFormat:#"%#/%#", documentsDirectory,#"tempfile.csv"];
//[urlData writeToFile:filePath atomically:YES];
BOOL newFile = [[NSFileManager defaultManager] createFileAtPath:filePath contents:urlData attributes:nil];
arrayOfDocuments = [[NSArray alloc] initWithObjects:
filePath, nil];
QLPreviewController *previewer = [[QLPreviewController alloc] init];
[self addSubview:previewer.view];
// Set data source
[previewer setDataSource:self];
// Which item to preview
[previewer setCurrentPreviewItemIndex:0];
}
}
/*---------------------------------------------------------------------------
*
*--------------------------------------------------------------------------*/
- (NSInteger) numberOfPreviewItemsInPreviewController: (QLPreviewController *) controller
{
return [arrayOfDocuments count];
}
/*---------------------------------------------------------------------------
*
*--------------------------------------------------------------------------*/
- (id <QLPreviewItem>)previewController: (QLPreviewController *)controller previewItemAtIndex:(NSInteger)index
{
// Break the path into it's components (filename and extension)
NSArray *fileComponents = [[arrayOfDocuments objectAtIndex: index] componentsSeparatedByString:#"."];
NSArray *filePaths = [[fileComponents objectAtIndex:0] componentsSeparatedByString:#"/"];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *filePath = [documentsDirectory stringByAppendingPathComponent:[((NSString *)[filePaths objectAtIndex:[filePaths count]-1]) stringByAppendingString:(NSString*)[fileComponents objectAtIndex:1]]];
// Use the filename (index 0) and the extension (index 1) to get path
BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:filePath];
if (fileExists) {
//
}
return [NSURL fileURLWithPath:filePath isDirectory:NO];
}
You don't add a preview controller's view to your view - you present the preview controller. And you should do that after setting the data source! So, in this order:
QLPreviewController* preview = [QLPreviewController new];
preview.dataSource = self;
[self presentViewController:preview animated:YES completion:nil];