2009-12-15 4 views
2

J'utilise le MFMailComposeViewController pour envoyer du courrier à partir d'une application. J'ai ajouté le code de l'exemple Apple à un UITableViewController, et tout fonctionne comme prévu lorsque je déclenche le modalViewController à partir d'un UIToolBarButton. Le problème vient quand je mets un UIActionSheet entre le UIToolBarButton et le code MFMailComposeViewController.Crash lors de l'utilisation de MFMailComposeViewController avec UIActionSheet

Je souhaite présenter à l'utilisateur l'option d'envoyer par courrier électronique ou de poster sur Facebook. Lorsque j'appelle les méthodes MFMailComposeViewController après le rejet du UIActionSheet, mon application se bloque lorsque la méthode essaie de charger le modalViewController. Code ci-dessous, des idées?

// 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:[email protected][email protected],[email protected]&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]]; 
} 
+0

Mise à jour sur ce ... d'autres postes ont eu le même problème, voir ce fil: http://stackoverflow.com/questions/1082954/presentmodalviewcontroller-crashes-my-app Essayé le sélecteur retardé, mais ça n'a pas marché pour moi. Jk – Alpinista

Répondre

1

En fait, David (ci-dessus commentaire) m'a mis sur la bonne voie. L'UIActionSheet provoquait l'invalidité de mon emailString ivar, donc j'ai déplacé l'appel à la UIActionSheet vers AVANT de construire le mailString. Maintenant tout fonctionne!

1

Je pense que votre problème est que vous avez besoin

[emailString retain]; 

c'est un objet autorelease, et je pense qu'il devient libéré après onEmailButtonTouch retours, de sorte qu'il est invalide lorsque votre feu de notification d'alerte.

+0

EmailString est un Ivar, donc n'est pas libéré jusqu'à ce que le VC est désallouée Jk – Alpinista

+1

si elle était une propriété marquée (conserver), alors ce serait le cas, mais vous auriez besoin de s'y référer comme self.emailString lorsque vous avez effectué l'affectation. Comme c'est le cas, il n'est pas automatiquement retenu pour vous. –

Questions connexes