我有一个函数可以将从本地 SQLite 数据库中提取的数据保存到 .CSV 文件中。
我的问题是此函数还会触发另一个将文件附加到电子邮件并发送的函数。由于文件尚未完成保存,附件作为空文件发送。
无论如何,我可以在将文件附加到电子邮件之前检查文件是否已完成保存吗?请在下面查看我的功能:
// When the tick is visible within the animation...
// Play the bellToneSound.
AudioServicesPlaySystemSound(bellToneSound);
// Creates a temporary GPS object that we will use to save our database as a .CSV file.
GPS *saveGPS = [[GPS alloc] init];
// Finds the phone's documents directory and creates a file path in order create a new file/folder there.
NSError *error = nil;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *dataPath = [documentsDirectory stringByAppendingPathComponent:@"/Jobs"];
if (![[NSFileManager defaultManager] fileExistsAtPath:dataPath]){
[[NSFileManager defaultManager] createDirectoryAtPath:dataPath withIntermediateDirectories:NO attributes:nil error:&error];
}
NSString *filePath = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:@"/Jobs/%@.csv", proposalNumber]];
// Creates our new file, with a name matching "jobNo.csv" overrites old one if it already exists.
[[NSFileManager defaultManager] createFileAtPath:filePath contents:nil attributes:nil];
// Creates a file handler which will allow us to write to our file.
NSFileHandle *myHandle = [NSFileHandle fileHandleForWritingAtPath:filePath];
// Creates and writes the first line to our CSV file, which tells the program reading it what the column titles are.
NSString *csvTitleString =@"Source/Monitor, Latitude, Longitude";
[myHandle writeData:[csvTitleString dataUsingEncoding:NSUTF8StringEncoding]];
// Creates initializes another string object which will hold each line we want to write.
NSString *csvString = [[NSString alloc] init];
// Declares an array and fills it with all GPS objects found in our Database.
NSArray *allGPS = [[NSArray alloc]initWithArray:[database getAll]];
// While the current index value is less than the length of the array write the GPS values into our file then take a new line.
for(int i=0;i<(allGPS.count);i++){
saveGPS = [allGPS objectAtIndex:i];
csvString = [NSString stringWithFormat:@"\n %@ %d, %@, %@", [saveGPS sourceMonitor], [[saveGPS positionNo] intValue], [saveGPS latitude], [saveGPS longitude]];
[myHandle seekToEndOfFile];
[myHandle writeData:[csvString dataUsingEncoding:NSUTF8StringEncoding]];
}
}
更新
这是您要求的代码。
NSString *docsDir;
NSString *realpath;
NSArray *dirPaths;
dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
docsDir = dirPaths[0];
realpath=[[NSString alloc] initWithString:[docsDir stringByAppendingPathComponent: [NSString stringWithFormat:@"/Jobs/temp.csv"]]];
NSFileManager *filemgr = [NSFileManager defaultManager];
if ([filemgr fileExistsAtPath: realpath ] == YES)
{
[self checkIfSaved];
}
else
{
NSLog(@"file found");
// Checks if the device can send email.
if([MFMailComposeViewController canSendMail]){
// Sets the subject to data from (our current proposal number).
[mail setSubject:[NSString stringWithFormat:@"Data from %@", proposalNumber]];
[mail setMessageBody:@"Please see the attached .CSV file." isHTML:NO];
// Finds the .CSV file we just saved, and attaches it to the email.
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *filePath = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:@"/Jobs/%@.csv", proposalNumber]];
NSData *attachment = [NSData dataWithContentsOfFile:[NSString stringWithFormat:@"%@", filePath]];
[mail addAttachmentData:attachment mimeType:@"text/csv" fileName:[NSString stringWithFormat:@"%@",proposalNumber]];
// Opens up the email screen.
[self presentViewController:mail animated:YES completion:NULL];
}
else
{
// Tells the user that there device cannot send email.
NSLog(@"This device cannot send email");
// Creates a popup window to inform the user that their location wasn't updates.
UIAlertController* alert = [UIAlertController alertControllerWithTitle:@"Error"
message:@"Unable to send email. Have you set up a mail account on this device?"
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* dismissAction = [UIAlertAction actionWithTitle:@"Dismiss" style:UIAlertActionStyleCancel handler:^(UIAlertAction * action) {}];
alert.view.tintColor = [UIColor orangeColor];
[alert addAction:dismissAction];
[self presentViewController:alert animated:YES completion:nil];
}
}
最佳答案
您需要安排您的代码,以便电子邮件部分在文件完全保存后才开始。有多种方法可以做到这一点:
轮询:您可以不断检查文件的状态,直到发现操作完成。有时轮询是不可避免的,但它通常是最糟糕的选择。不要走这条路。
完成例程:文件保存方法可以采用一个参数,该参数是保存完成时要执行的代码块。这很常见,你会在各种 iOS 框架中随处可见。例如,
NSURLSession
有一个-dataTaskWithURL:completionHandler:
方法。加载请求的数据后,将调用完成处理程序。串行执行:将文件保存代码放在一个 block 中,将邮件发送代码放在另一个 block 中。然后,您可以使用
NSOperationQueue
或直接使用 Grand Central Dispatch 将两个 block 调度到一个串行队列中,这样第二个 block 将在第一个 block 完成后才开始。
完成例程方法和串行执行方法都是确保您在文件保存之前不启动电子邮件进程的合理方法,因此请选择对您来说最简单的方法。
关于ios - 电子邮件附件不起作用,因为文件尚未完成保存?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33306251/