Danut Pralea „s answer jest wielka, jednak kod wydaje się być zbyt długo dla kogoś szukającego prosty sposób do wysłać załącznik za pośrednictwem poczty elektronicznej programowo .
Istotą
I przycina swoją odpowiedź do wykupienia tylko ważnych bitów, a także refactored go tak:
MFMailComposeViewController *mailComposer = [[MFMailComposeViewController alloc] init];
mailComposer.mailComposeDelegate = self;
mailComposer.subject = @"Sample subject";
mailComposer.toRecipients = @[@"[email protected]", @"[email protected]", ...];
mailComposer.ccRecipients = @[@"[email protected]", @"[email protected]", ...];
[mailComposer setMessageBody:@"Sample body" isHTML:NO];
NSData *fileData = [NSData dataWithContentsOfFile:filePath];
[mailComposer addAttachmentData:fileData
mimeType:mimeType
fileName:fileName];
[self presentViewController:mailComposer animated:YES completion:nil];
To w zasadzie sedno tego, to wystarczy jako to jest. Jeśli, na przykład, umieścisz ten kod w akcji przycisku, wyświetli on wiadomość e-mail przedstawiającą ekran z wypełnionymi polami, a także plik, który chcesz dołączyć do wiadomości e-mail.
Dalsze Reading
ramowa
MFMailComposeViewController
jest zgodnie z ramami MessageUI
, więc z niego korzystać, import (jeśli jeszcze tego nie zrobiły) Ramy tak:
#import <MessageUI/MessageUI.h>
Sprawdzanie poczty Poczta
Teraz po uruchomieniu kodu źródłowego, a jeszcze nie skonfigurowałeś konta pocztowego na swoim urządzeniu, (nie wiesz, co to jest na symulatorze), ten kod spowoduje awarię aplikacji. Wygląda na to, że jeśli konto pocztowe nie jest jeszcze skonfigurowane, wykonanie [[MFMailComposeViewController alloc] init]
nadal spowoduje, że mailComposer
będzie zerowe, causing the crash.Jak answer w połączonej pytanie stwierdza:
Należy sprawdzić to MFMailComposeViewController są w stanie wysyłać pocztę tuż przed wysłaniem
Można to zrobić za pomocą metody canSendMail tak:
if (![MFMailComposeViewController canSendMail]) {
[self openCannotSendMailDialog];
return;
}
Możesz to naprawić przed wykonaniem [[MFMailComposeViewController alloc] init]
, aby natychmiast powiadomić użytkownika.
Handling cannotSendMail
If canSendMail
zwraca false, według Apple Dev Docs, co oznacza, że urządzenie nie jest skonfigurowany do wysyłania poczty. To could mean, że być może użytkownik nie skonfigurował jeszcze swojego konta pocztowego. Aby pomóc użytkownikowi w tym, możesz zaoferować open the Mail app i skonfigurować swoje konto. Można to zrobić tak:
NSURL *mailUrl = [NSURL URLWithString:@"message://"];
if ([[UIApplication sharedApplication] canOpenURL:mailUrl]) {
[[UIApplication sharedApplication] openURL:mailUrl];
}
Następnie można wdrożyć openCannotSendMailDialog
tak:
- (void)openCannotSendMailDialog
{
UIAlertController *alert =
[UIAlertController alertControllerWithTitle:@"Error"
message:@"Cannot send mail."
preferredStyle:UIAlertControllerStyleAlert];
NSURL *mailUrl = [NSURL URLWithString:@"message://"];
if ([[UIApplication sharedApplication] canOpenURL:mailUrl]) {
[alert addAction:
[UIAlertAction actionWithTitle:@"Open Mail"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * _Nonnull action) {
[[UIApplication sharedApplication] openURL:mailUrl];
}]];
[alert addAction:
[UIAlertAction actionWithTitle:@"Cancel"
style:UIAlertActionStyleCancel
handler:^(UIAlertAction * _Nonnull action) {
}]];
} else {
[alert addAction:
[UIAlertAction actionWithTitle:@"OK"
style:UIAlertActionStyleCancel
handler:^(UIAlertAction * _Nonnull action) {
}]];
}
[self presentViewController:alert animated:YES completion:nil];
}
typów MIME
Jeśli tak jak ja, że zapomniałeś/pewności, który mimeType
używać , here to zasób, którego możesz użyć. Najprawdopodobniej wystarcza text/plain
, jeśli plik, który dołączasz, jest zwykłym tekstem lub image/jpeg
/ dla obrazów.
Delegat
Jak zapewne zauważyliście, Xcode rzuca nam ostrzeżenie o następującej linii:
mailComposer.mailComposeDelegate = self;
To dlatego, że nie zostały jeszcze ustalone Nas do dostosowania się do odpowiedniego protokołu i wdrożenia metoda delegata. Jeśli chcesz odbierać zdarzenia, czy poczta została anulowana, zapisywane wysyłane lub nawet udało wysyłania, trzeba ustawić klasę zgodne z protokołem MFMailComposeViewControllerDelegate
i obsługiwać following events:
- MFMailComposeResultSent
- MFMailComposeResultSaved
- MFMailComposeResultCancelled
- MFMailComposeResultFailed
Według Apple Dev Docs (podkreślenie moje):
Administrator wiadomości e-mailowej komponentowej nie jest automatycznie usuwany z konta. Gdy użytkownik dotknie przycisków, aby wysłać wiadomość e-mail lub anuluje interfejs, kontroler widoku wiadomości e-mail decyduje o sposobie jego delegata. Twoja implementacja tej metody musi wyraźnie odwołać kontroler widoku.
Mając to na uwadze, możemy zaimplementować metodę delegata tak:
- (void)mailComposeController:(MFMailComposeViewController *)controller
didFinishWithResult:(MFMailComposeResult)result
error:(NSError *)error
{
switch (result) {
case MFMailComposeResultSent:
// Mail was sent
break;
case MFMailComposeResultSaved:
// Mail was saved as draft
break;
case MFMailComposeResultCancelled:
// Mail composition was cancelled
break;
case MFMailComposeResultFailed:
//
break;
default:
//
break;
}
// Dismiss the mail compose view controller.
[controller dismissViewControllerAnimated:YES completion:nil];
}
Wnioski
Ostateczny kod może wyglądać tak:
- (void)openMailComposerWithSubject:(NSString *)subject
toRecipientArray:(NSArray *)toRecipientArray
ccRecipientArray:(NSArray *)ccRecipientArray
messageBody:(NSString *)messageBody
isMessageBodyHTML:(BOOL)isHTML
attachingFileOnPath:(NSString)filePath
mimeType:(NSString *)mimeType
{
if (![MFMailComposeViewController canSendMail]) {
[self openCannotSendMailDialog];
return;
}
MFMailComposeViewController *mailComposer =
[[MFMailComposeViewController alloc] init];
mailComposer.mailComposeDelegate = self;
mailComposer.subject = subject;
mailComposer.toRecipients = toRecipientArray;
mailComposer.ccRecipients = ccRecipientArray;
[mailComposer setMessageBody:messageBody isHTML:isHTML];
NSData *fileData = [NSData dataWithContentsOfFile:filePath];
NSString *fileName = filePath.lastPathComponent;
[mailComposer addAttachmentData:fileData
mimeType:mimeType
fileName:fileName];
[self presentViewController:mailComposer animated:YES completion:nil];
}
- (void)openCannotSendMailDialog
{
UIAlertController *alert =
[UIAlertController alertControllerWithTitle:@"Error"
message:@"Cannot send mail."
preferredStyle:UIAlertControllerStyleAlert];
NSURL *mailUrl = [NSURL URLWithString:@"message://"];
if ([[UIApplication sharedApplication] canOpenURL:mailUrl]) {
[alert addAction:
[UIAlertAction actionWithTitle:@"Open Mail"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * _Nonnull action) {
[[UIApplication sharedApplication] openURL:mailUrl];
}]];
[alert addAction:
[UIAlertAction actionWithTitle:@"Cancel"
style:UIAlertActionStyleCancel
handler:^(UIAlertAction * _Nonnull action) {
}]];
} else {
[alert addAction:
[UIAlertAction actionWithTitle:@"OK"
style:UIAlertActionStyleCancel
handler:^(UIAlertAction * _Nonnull action) {
}]];
}
[self presentViewController:alert animated:YES completion:nil];
}
- (void)mailComposeController:(MFMailComposeViewController *)controller
didFinishWithResult:(MFMailComposeResult)result
error:(NSError *)error
{
NSString *message;
switch (result) {
case MFMailComposeResultSent:
message = @"Mail was sent.";
break;
case MFMailComposeResultSaved:
message = @"Mail was saved as draft.";
break;
case MFMailComposeResultCancelled:
message = @"Mail composition was cancelled.";
break;
case MFMailComposeResultFailed:
message = @"Mail sending failed.";
break;
default:
//
break;
}
// Dismiss the mail compose view controller.
[controller dismissViewControllerAnimated:YES completion:^{
if (message) {
UIAlertController *alert =
[UIAlertController alertControllerWithTitle:@"Confirmation"
message:message
preferredStyle:UIAlertControllerStyleAlert];
[alert addAction:
[UIAlertAction actionWithTitle:@"OK"
style:UIAlertActionStyleCancel
handler:^(UIAlertAction * _Nonnull action) {
}]];
[self presentViewController:alert animated:YES completion:nil];
}
}];
}
Wygląd przycisku:
- (IBAction)mailButtonTapped:(id)sender
{
NSString *reportFilePath = ...
[self openMailComposerWithSubject:@"Report Files"
toRecipientArray:mainReportRecipientArray
ccRecipientArray:subReportRecipientArray
messageBody:@"I have attached report files in this email"
isMessageBodyHTML:NO
attachingFileOnPath:reportFilePath
mimeType:@"text/plain"];
}
W pewnym sensie wyskoczyłem tutaj, ale można, z przymrużeniem oka, wziąć i użyć kodu, który tutaj zamieściłem. Oczywiście istnieje potrzeba dostosowania go do swoich wymagań, ale to zależy od Ciebie. (Zmieniłem też tę odpowiedź z mojego działającego kodu źródłowego, więc mogą być gdzieś błędy, proszę zrób komentarz, jeśli znajdziesz :))
Spróbuj zalogować się myData, aby sprawdzić, czy nie zwraca wartości zerowej. – EmilioPelaez
Jest pusty ... jak mogę uzyskać plik? Edytuję mój oryginalny wpis, aby pokazać, gdzie utworzę plik. – coder
Wygląda na to, że 'filePath = [[NSBundle mainBundle] pathForResource: @" expenses "ofType: @" csv "];' nie otrzymuje ścieżki do pliku, którego szukasz. Jeśli mam rację, ta metoda po prostu pobiera zasoby w twoim folderze .app. Zalecam, aby uzyskać ścieżkę w taki sam sposób, jak w przypadku metody exportData. – EmilioPelaez