Сбой при использовании MFMailComposeViewController с UIActionSheet - PullRequest
2 голосов
/ 15 декабря 2009

Я использую MFMailComposeViewController для отправки почты из приложения. Я добавил код из примера Apple в UITableViewController, и все работает как ожидалось, когда я запускаю modalViewController из UIToolBarButton. Проблема возникает, когда я ставлю UIActionSheet между UIToolBarButton и MFMailComposeViewController кодом.

Я хочу предоставить пользователю возможность отправить по электронной почте или опубликовать в Facebook. Когда я вызываю MFMailComposeViewController методы после закрытия UIActionSheet, мое приложение падает, когда метод пытается загрузить modalViewController. Код ниже, есть идеи?

// UIToolBarButton generates the email string and displays the UIActionSheet with email options
- (void)onEmailButtonTouch
{
    int mySection;
    int myRow;
    emailString = [NSString stringWithFormat:@"<b><p>Ten Essentials Check List</b><br />%@</p>", [myList valueForKey:@"listName"]];

    for (mySection = 0; mySection < [[fetchedResultsController sections] count]; mySection ++)
    {
        NSString *sectionName = [NSString stringWithFormat:@"<p><b>%@ Group</b></p><ul>", [[[fetchedResultsController sections] objectAtIndex:mySection] name]];
        emailString = [emailString stringByAppendingString:sectionName];
        id <NSFetchedResultsSectionInfo> sectionInfo = [[fetchedResultsController sections] objectAtIndex:mySection];

        for (myRow = 0; myRow < [sectionInfo numberOfObjects]; myRow ++)
        {
            // Get the managedObject
            NSIndexPath *indexPath = [NSIndexPath indexPathForRow:myRow inSection:mySection];
            NSManagedObject *managedObject = [fetchedResultsController objectAtIndexPath:indexPath];

            //Get the related Item object
            Item *item  = [managedObject valueForKey:@"item"];
            NSString *itemName = [NSString stringWithFormat:@"<li>%@</li>", item.itemName];
            emailString = [emailString stringByAppendingString:itemName];
        }

        emailString = [emailString stringByAppendingString:@"</ul>"];
    }

    NSLog(@"email string = :\n%@", emailString);
    [self showEmailOptions];
}

// Display an UIActionSheet with email/facebook buttons
-(void)showEmailOptions
{
    UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:@"eMail Options" delegate:self cancelButtonTitle:@"Cancel" destructiveButtonTitle:NULL otherButtonTitles:@"Send List via Email", @"Post List to Facebook", NULL];
    [actionSheet showFromToolbar:self.navigationController.toolbar];
    [actionSheet release];
}

// Call the MFMailComposeViewController methods if the user selects the Email button of the actioSheet
- (void)actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex
{
    if (buttonIndex == 0)
    {
        NSLog(@"Opening email");
        [self showPicker];
    }
}


-(void)showPicker
{
    // This sample can run on devices running iPhone OS 2.0 or later  
    // The MFMailComposeViewController class is only available in iPhone OS 3.0 or later. 
    // So, we must verify the existence of the above class and provide a workaround for devices running 
    // earlier versions of the iPhone OS. 
    // We display an email composition interface if MFMailComposeViewController exists and the device can send emails.
    // We launch the Mail application on the device, otherwise.

    Class mailClass = (NSClassFromString(@"MFMailComposeViewController"));
    if (mailClass != nil)
    {
        // We must always check whether the current device is configured for sending emails
        if ([mailClass canSendMail])
        {
            [self displayComposerSheet];
        }
        else
        {
            [self launchMailAppOnDevice];
        }
    }
    else
    {
        [self launchMailAppOnDevice];
    }
}


// Displays an email composition interface inside the application. Populates all the Mail fields. 
-(void)displayComposerSheet
{
    MFMailComposeViewController *picker = [[MFMailComposeViewController alloc] init];
    picker.mailComposeDelegate = self;
    [picker setSubject:@"Here is your gear check list!"];

    // Attach an image to the email
    NSString *path = [[NSBundle mainBundle] pathForResource:@"Checkmark_icon" ofType:@"png"];
    NSData *myData = [NSData dataWithContentsOfFile:path];
    [picker addAttachmentData:myData mimeType:@"image/png" fileName:@"Checkmark_icon"];

    // Fill out the email body text
    NSString *emailBody = emailString;
    [picker setMessageBody:emailBody isHTML:YES];

    // CRASH HAPPENS ON THE LINE BELOW //
    [self presentModalViewController:picker animated:YES];
    [picker release];
}


// Dismisses the email composition interface when users tap Cancel or Send. Proceeds to update the message field with the result of the operation.
- (void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error 
{   
    //message.hidden = NO;
    // Notifies users about errors associated with the interface
    switch (result)
    {
        case MFMailComposeResultCancelled:
            NSLog (@"Result: canceled");
            break;
        case MFMailComposeResultSaved:
            NSLog (@"Result: saved");
            break;
        case MFMailComposeResultSent:
            NSLog (@"Result: sent");
            break;
        case MFMailComposeResultFailed:
            NSLog (@"Result: failed");
            break;
        default:
            NSLog (@"Result: not sent");
            break;
    }

    [self dismissModalViewControllerAnimated:YES];
}


#pragma mark -
#pragma mark Workaround
// Launches the Mail application on the device.
-(void)launchMailAppOnDevice
{
    NSString *recipients = @"mailto:first@example.com?cc=second@example.com,third@example.com&subject=Here is your gear check list!";
    NSString *body = emailString;
    NSString *email = [NSString stringWithFormat:@"%@%@", recipients, body];
    email = [email stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];

    [[UIApplication sharedApplication] openURL:[NSURL URLWithString:email]];
}

Ответы [ 2 ]

1 голос
/ 15 декабря 2009

На самом деле, Дэвид (выше комментарий) поставил меня на правильный путь. Из-за UIActionSheet мой ivar emailString стал недействительным, поэтому я переместил вызов в UIActionSheet ПЕРЕД созданием emailString. Теперь все работает!

1 голос
/ 15 декабря 2009

Я думаю, что ваша проблема в том, что вам нужно

[emailString retain];

это объект авто-релиза, и я думаю, что он освобождается после возврата onEmailButtonTouch, поэтому он недействителен при срабатывании уведомления.

...