Reputation: 518
I've been racking my brain over this for the past week now and can't quite figure out how to go about this.
I currently have an app that takes in survey data, saves it as a csv file in the form of surveydata-mm-dd-yyyy. This usually goes out to events that last multiple days so a normal event weekend would be
surveydata-09-13-2014 surveydata-09-14-2014 surveydata-09-15-2014
Now I want the person who is at these events to be able to simply click a button that will prepend an e-mail with all those files which are being stored in the apps documents folder.
I have it all pretty much setup and functioning minus being able to tell the app to look for those files with those names and to include them in the e-mail.
Here is the code I have
- (IBAction)emailButton:(id)sender {
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat:@"MM-dd-yyyy"];
NSString *dateString = [dateFormat stringFromDate:[NSDate date]];
NSString *path = [[self applicationDocumentsDirectory].path
stringByAppendingPathComponent:[NSString stringWithFormat:@"_SurveyData_%@.csv",dateString]];
/* if(![[NSFileManager defaultManager] fileExistsAtPath:path]) {*/
MFMailComposeViewController *mailer = [[MFMailComposeViewController alloc] init];
mailer.mailComposeDelegate = self;
[mailer setSubject:@"CSV File"];
[mailer setToRecipients:toRecipents];
[mailer addAttachmentData:[NSData dataWithContentsOfFile:@"_SurveyData_%@.csv"]
mimeType:@"text/csv"
fileName:@"FileName"];
[self presentModalViewController:mailer animated:YES];
//}
}
If somebody could please help me out as I feel like I'm so close I'm just waiting for it to all click and make sense.
Please let me know if I'm missing something or my code is too vague.
This is the code that i'm using to write the data to the CSV for better understanding of how it's all going down.
-(void)writeSurveyDataToCSV:(NSString *)text {
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat:@"MM-dd-yyyy"];
NSString *dateString = [dateFormat stringFromDate:[NSDate date]];
NSString *path = [[self applicationDocumentsDirectory].path
stringByAppendingPathComponent:[NSString stringWithFormat:@"_SurveyData_%@.csv",dateString]];
if(![[NSFileManager defaultManager] fileExistsAtPath:path]) {
NSString *header = @" gender,age,zip code,duration(sec), own a bike?,response1,response2,response3,response4,response5,response6, response7, response8, response9\n";
[header writeToFile:path atomically:YES
encoding:NSUTF8StringEncoding error:nil];
}
text = [text stringByAppendingString:@"\n"];
NSFileHandle *fileHandle = [NSFileHandle fileHandleForWritingAtPath:path];
[fileHandle seekToEndOfFile];
[fileHandle writeData:[text dataUsingEncoding:NSUTF8StringEncoding]];
}
EDIT: Thanks to Danh's guidance here's my solution
- (IBAction)emailButton:(id)sender {
NSArray *toRecipents = [NSArray arrayWithObject:@"[email protected]"];
MFMailComposeViewController *mailer = [[MFMailComposeViewController alloc] init];
mailer.mailComposeDelegate = self;
[mailer setSubject:@"CSV File"];
[mailer setToRecipients:toRecipents];
NSArray *filenames = [self filesNamesStartingAt:[NSDate date] count:165];
[self attachFilesNamed:filenames toMailer:mailer];
[self presentModalViewController:mailer animated:YES];
}
// answer count strings, named for days starting at date and the count-1 following days
- (NSArray *)filesNamesStartingAt:(NSDate *)date count:(NSInteger)count {
NSMutableArray *result = [NSMutableArray array];
static NSDateFormatter *dateFormat;
if (!dateFormat) {
dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat:@"MM-dd-yyyy"];
}
for (int i=0; i<count; ++i) {
NSString *dateString = [dateFormat stringFromDate:date];
NSString *path = [[self applicationDocumentsDirectory].path
stringByAppendingPathComponent:[NSString stringWithFormat:@"_SurveyData_%@.csv",dateString]];
[result addObject:path];
date = [self addDayToDate:date];
}
for (int i=0; i<count; ++i) {
NSString *dateString = [dateFormat stringFromDate:date];
NSString *path = [[self applicationDocumentsDirectory].path
stringByAppendingPathComponent:[NSString stringWithFormat:@"_SurveyData_%@.csv",dateString]];
[result addObject:path];
date = [self subDayToDate:date];
}
return result;
}
// answer a new date, advanced one day from the passed date
- (NSDate *)addDayToDate:(NSDate *)date {
NSDateComponents *components = [[NSDateComponents alloc] init];
[components setDay:1];
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
return [gregorian dateByAddingComponents:components toDate:date options:0];
}
- (NSDate *)subDayToDate:(NSDate *)date {
NSDateComponents *components = [[NSDateComponents alloc] init];
[components setDay:-1];
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
return [gregorian dateByAddingComponents:components toDate:date options:0];
}
- (void)attachFilesNamed:(NSArray *)paths toMailer:(MFMailComposeViewController *)mailer {
for (NSString *path in paths) {
if ([[NSFileManager defaultManager] fileExistsAtPath:path]) {
NSData *data = [NSData dataWithContentsOfFile:path];
[mailer addAttachmentData:data mimeType:@"text/csv" fileName:path];
} else {
NSLog(@"warning, no file at path %@", path);
}
}
}
- (NSURL *)applicationDocumentsDirectory {
return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory
inDomains:NSUserDomainMask] lastObject];
}
Upvotes: 0
Views: 65
Reputation: 62676
It does look like you're very close. Maybe decomposing the problem a little more is what's needed:
Start with a method that will create the file names for several days starting at a given day...
// answer count strings, named for days starting at date and the count-1 following days
- (NSArray *)filesNamesStartingAt:(NSDate *)date count:(NSInteger)count {
NSMutableArray *result = [NSMutableArray array];
static NSDateFormatter *dateFormat;
if (!dateFormat) {
dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat:@"MM-dd-yyyy"];
}
for (int i=0; i<count; ++i) {
NSString *dateString = [dateFormat stringFromDate:date];
NSString *path = [[self applicationDocumentsDirectory].path
stringByAppendingPathComponent:[NSString stringWithFormat:@"_SurveyData_%@.csv",dateString]];
[result addObject:path];
date = [self addDayToDate:date];
}
return result;
}
// answer a new date, advanced one day from the passed date
- (NSDate *)addDayToDate:(NSDate *)date {
NSDateComponents *components = [[NSDateComponents alloc] init];
[components setDay:1];
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
return [gregorian dateByAddingComponents:components toDate:date options:0];
}
Now, add a method that will attach a set of named files to a mail controller:
- (void)attachFilesNamed:(NSArray *)paths toMailer:(MFMailComposeViewController *)mailer {
for (NSString *path in paths) {
if ([[NSFileManager defaultManager] fileExistsAtPath:path]) {
NSData *data = [NSData dataWithContentsOfFile:path];
[mailer addAttachmentData:data mimeType:@"text/csv" fileName:path];
} else {
NSLog(@"warning, no file at path %@", path);
}
}
}
The rest practically writes itself (I hope)...
MFMailComposeViewController *mailer = [[MFMailComposeViewController alloc] init];
mailer.mailComposeDelegate = self;
[mailer setSubject:@"CSV File"];
[mailer setToRecipients:toRecipents];
NSArray *filenames = [self fileNamesStartingAt:[NSDate date] count:3];
[self attachFilesNamed:filenames toMailer:mailer];
Note that, as written, this will use today and the next two days for filenames. If this isn't your requirement, you can tweak the addDay method to create a subtract days method, then work with those in tandem.
Upvotes: 1
Reputation: 1129
You're creating a filepath, but in the [mailer addAttachmentData] call, you're not passing in that path as I assume you intended--instead it's just getting the string that you used to build the path, so your NSData is going to be nil because it's not a complete path to anything on disk. Try changing that line to [mailer addAttachmentData:[NSData dataWithContentsOfFile:path]]
Upvotes: 1