3

我在我的应用程序中遇到了一个奇怪的问题,我需要你的帮助!
我正在使用 MFMailComposeViewController 发送带有附件数据的电子邮件。附件是 PDF、CSV 或 XLS 文件。ZIP 文件也可以添加到邮件中。

在大多数情况下一切正常,但有时(实际上很常见),当附件是 XLS 并添加了 ZIP 时,我收到多个内存警告并且作曲家返回 MFMailComposeResultFailed,并出现一个根本没有帮助的错误(只说代码错误 1,“操作无法完成。(MFMailComposeErrorDomain 错误 1.)”)。

我的问题是它为什么这样做?我假设内存警告告诉我一些事情没有得到很好的管理,但我不知道是什么......

这是我发送电子邮件的代码

-(void) sendMail {

    MFMailComposeViewController *picker = [[MFMailComposeViewController alloc] init]; 
    [self prepareMailPicker:picker];

    NSString *filePath = [self getFilePath:pType];

    NSString *zipFile = [self getZipPath];

    NSString *mimeType;
    int userPhoto = [User getCSVPhoto];

    switch (pType) {
        case EPDF:
            mimeType = @"application/pdf";
            userPhoto = [User getPDFPhoto];
            break;
        case ECSV:
            mimeType = @"text/csv";
            break;
        case EExcel:
            mimeType = @"application/vnd.ms-excel";
            break;

        default:
            break;
    }

    NSData *attachmentData = [NSData dataWithContentsOfFile:filePath];
    [picker addAttachmentData:attachmentData mimeType:mimeType fileName:[filePath lastPathComponent]];

    if (userPhoto == 1 && shouldAddZip) {
        NSData *zipData = [NSData dataWithContentsOfFile:zipFile];
        [picker addAttachmentData:zipData mimeType:@"application/zip" fileName:[zipFile lastPathComponent]];
    }

    shouldAddZip = NO;

    [self presentModalViewController:picker animated:YES];
}

-(void) prepareMailPicker:(MFMailComposeViewController*)picker {

    picker.mailComposeDelegate = (id<MFMailComposeViewControllerDelegate>)self;

    picker.navigationBar.tintColor = grayDark;

    [picker setSubject:[TextManager textForKey:@"EMAIL_SUBJECT"]];

    NSString *email = [[User currentUser] getEmail];

    if (email && ![email isEqualToString:@""])
        [picker setToRecipients:[NSArray arrayWithObject:email]];

    NSString *emailBody = [TextManager textForKey:@"EMAIL_TEXT"];
    [picker setMessageBody:emailBody isHTML:YES];
}

任何帮助将不胜感激!

编辑:正如@matt 所问,这里有一个日志来证明没有设置为 nil :

filePath : /var/mobile/Applications/A57F5CD2-E3FE-4417-8810-D746A22CF434/Documents/iNdF_Export_2012-11-19.xls
zipFile : /var/mobile/Applications/A57F5CD2-E3FE-4417-8810-D746A22CF434/Documents/iNdF_recus_2012-11-19.zip
attachmentData : (NSConcreteData *) <0x1d9c3c20> 53 874 bytes
zipData : (NSConcreteData *) <0x1f989100> 6 838 456 bytes
4

3 回答 3

1

正如您所说,鉴于您收到的内存警告,问题似乎很可能与内存管理有关。

您的代码保留了对第一个文件的 attachmentData 的引用计数,即使它出去获取第二个文件的 zipData 也是如此。在内部,选择器可能正在复制该数据……</p>

因此,您越能尽早释放对大数据的引用,就越有可能不会收到内存警告。

如果问题是由于内存不足导致选择器无法完成附件,并且您可以通过提前释放来解决它,那么按照以下方式分解代码可能会对您有所帮助。

- (void)sendMailPicker:(MFMailComposeViewController*)picker addAttachmentUsingMimeType:(NSString*)mimeType {
    NSString *filePath = [self getFilePath:pType];
    NSData *attachmentData = [NSData dataWithContentsOfFile:filePath];
    [picker addAttachmentData:attachmentData mimeType:mimeType fileName:[filePath lastPathComponent]];
}

- (void)sendMailAddPhotoUsingPicker:(MFMailComposeViewController*)picker {
    NSString *zipFile = [self getZipPath];
    NSData *zipData = [NSData dataWithContentsOfFile:zipFile];
    [picker addAttachmentData:zipData mimeType:@"application/zip" fileName:[zipFile lastPathComponent]];
}

- (void)sendMail {

    MFMailComposeViewController *picker = [[MFMailComposeViewController alloc] init]; 
    [self prepareMailPicker:picker];

    NSString *mimeType;
    int userPhoto = [User getCSVPhoto];

    switch (pType) {
        case EPDF:
            mimeType = @"application/pdf";
            userPhoto = [User getPDFPhoto];
            break;
        case ECSV:
            mimeType = @"text/csv";
            break;
        case EExcel:
            mimeType = @"application/vnd.ms-excel";
            break;

        default:
            break;
    }

    [self sendMailPicker:picker addAttachmentUsingMimeType:mimeType];
    if (userPhoto == 1 && shouldAddZip) {
        [self sendMailAddPhotoUsingPicker:picker];
    }

    shouldAddZip = NO;

    [self presentModalViewController:picker animated:YES];
}
于 2012-11-21T06:38:12.277 回答
0

我猜这个问题与内存有关,当您创建 NSData 时,您会在堆中创建。如果它太大,您将开始收到内存警告。避免内存的一种方法是创建内存映射的 NSData 或 NSStream,但我不知道如何将 NSStream 集成到邮件编写器中。您的附件的平均大小是多少?
您还可以尝试使用分配来分析您的应用程序,以查看您的应用程序的内存占用量,可能已经太高了。

于 2012-11-21T06:47:32.170 回答
0

就像我之前遇到的一些问题一样。1. 请使用“Reachability”类文件检查是否有 Internet 可用性。2. 请检查您的数据大小是否在限制范围内。3. 请检查您使用您的设备配置了您的电子邮件 ID。你也可以调用[yourobj cansendmail]函数来检查它是否可以发送邮件。

于 2012-11-27T07:23:01.830 回答