Danut Pralea 's answer là rất tốt, tuy nhiên các mã có vẻ là quá dài đối với một ai đó tìm kiếm một cách đơn giản -gửi tập tin đính kèm qua email programatically .
Các Gist
Tôi tỉa câu trả lời của mình để đưa ra chỉ các bit quan trọng, cũng như refactored nó như vậy:
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];
Đó là về cơ bản các ý chính của nó, điều này là đủ như nó là. Ví dụ: nếu bạn đặt mã này vào hành động của nút, nó sẽ hiển thị một màn hình soạn email với các trường tương ứng được điền sẵn, cũng như có tệp bạn muốn đính kèm vào email.
Đọc thêm
Khung
Các MFMailComposeViewController
là dưới khung MessageUI
, vì vậy sử dụng nó, nhập khẩu (nếu bạn đã chưa xong) Khung như vậy:
#import <MessageUI/MessageUI.h>
Kiểm tra khả năng thư
Bây giờ, khi bạn chạy mã nguồn và bạn chưa thiết lập tài khoản thư trên thiết bị của mình, (không chắc chắn hành vi là gì trên trình mô phỏng), mã này sẽ làm hỏng ứng dụng của bạn. Dường như nếu tài khoản thư chưa được thiết lập, việc thực hiện [[MFMailComposeViewController alloc] init]
sẽ vẫn dẫn đến số mailComposer
là số không, causing the crash.Khi answer trong câu hỏi liên quan khẳng định:
Bạn nên kiểm tra là MFMailComposeViewController có thể gửi email của bạn ngay trước khi gửi
Bạn có thể làm điều này bằng cách sử dụng phương pháp canSendMail như vậy:
if (![MFMailComposeViewController canSendMail]) {
[self openCannotSendMailDialog];
return;
}
Bạn có thể đặt quyền này trước khi thực hiện [[MFMailComposeViewController alloc] init]
để bạn có thể thông báo cho người dùng ngay lập tức.
Xử lý cannotSendMail
Nếu canSendMail
lợi nhuận sai sự thật, theo Apple Dev Documents, có nghĩa rằng thiết bị không được cấu hình để gửi thư. Điều này could mean có thể người dùng chưa thiết lập tài khoản Thư của họ. Để giúp người dùng với điều đó, bạn có thể cung cấp cho open the Mail app và thiết lập tài khoản của họ. Bạn có thể làm điều này như sau:
NSURL *mailUrl = [NSURL URLWithString:@"message://"];
if ([[UIApplication sharedApplication] canOpenURL:mailUrl]) {
[[UIApplication sharedApplication] openURL:mailUrl];
}
Bạn có thể sau đó thực hiện openCannotSendMailDialog
như vậy:
- (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];
}
Mime loại
Nếu như tôi, bạn quên/không chắc chắn mà mimeType
sử dụng , here là tài nguyên bạn có thể sử dụng. Có lẽ hầu hết, text/plain
là đủ, nếu tệp bạn đang đính kèm chỉ là văn bản thuần túy hoặc image/jpeg
/image/png
cho hình ảnh.
Đại biểu
Như bạn có thể nhận thấy, Xcode ném chúng tôi một lời cảnh báo về dòng sau:
mailComposer.mailComposeDelegate = self;
Điều này là do chúng ta chưa thiết lập ourself để phù hợp với các giao thức thích hợp và thực hiện phương thức ủy nhiệm của nó. Nếu bạn muốn nhận sự kiện dù thư đã bị hủy bỏ, lưu, gửi hoặc thậm chí thất bại trong việc gửi, bạn cần phải thiết lập lớp học của bạn để phù hợp với các giao thức MFMailComposeViewControllerDelegate
, và xử lý các following events:
- MFMailComposeResultSent
- MFMailComposeResultSaved
- MFMailComposeResultCancelled
- MFMailComposeResultFailed
Theo Apple Dev Documents (tôi nhấn mạnh):
Bộ điều khiển chế độ xem thư soạn không bị loại bỏ tự động. Khi người dùng chạm vào các nút để gửi email hoặc hủy giao diện, trình điều khiển chế độ xem thư soạn thư sẽ gọi phương thức mailComposeController:didFinishWithResult:error: của người được ủy quyền. Việc triển khai phương pháp đó của bạn phải loại bỏ trình điều khiển chế độ xem một cách rõ ràng.
Với điều này trong tâm trí, sau đó chúng tôi có thể thực hiện các phương pháp đại biểu như vậy:
- (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];
}
Kết luận
Mã cuối cùng có thể trông giống như vậy:
- (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];
}
}];
}
Với thao tác nút trông giống như:
- (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"];
}
tôi loại đi quá nhiệt tình ở đây, nhưng bạn có thể, với một hạt muối, lấy và sử dụng đoạn code tôi được đăng ở đây. Tất nhiên có một nhu cầu để thích nghi nó với yêu cầu của bạn, nhưng đó là vào bạn. (Tôi cũng đã sửa đổi câu trả lời này từ mã nguồn đang hoạt động của mình, vì vậy có thể có lỗi ở đâu đó, vui lòng bình luận nếu bạn tìm thấy một :))
Hãy thử đăng nhập myData để xem nó có không trả về không. – EmilioPelaez
Nó là null ... làm thế nào để tôi có được tập tin? Tôi đang chỉnh sửa bài đăng gốc của mình để hiển thị nơi tôi tạo tệp. – coder
Có vẻ như 'filePath = [[NSBundle mainBundle] pathForResource: @" costs "ofType: @" csv "];' không nhận được đường dẫn của tệp bạn đang tìm kiếm. Nếu tôi đúng, phương thức đó chỉ nhận được tài nguyên bên trong thư mục .app của bạn. Tôi khuyên bạn nên lấy đường dẫn giống như cách bạn làm trong phương thức exportData. – EmilioPelaez