简体   繁体   中英

Closing Address Book in iOS

I know how to open up and send an email in iOS using MFMailComposeViewController . The code below will let the user write and send an email, and then go straight back to the app.

- (IBAction)sendEmail:(id)sender {
        // Email Subject
        NSString *emailTitle = @"Test";
        // Email Content
        NSString *messageBody = @"Test";
        // To address
        NSArray *toRecipents = [NSArray arrayWithObject:@"te@gmail.com"];


        MFMailComposeViewController *mc = [[MFMailComposeViewController alloc] init];
        mc.mailComposeDelegate = self;
        [mc setSubject:emailTitle];
        [mc setMessageBody:messageBody isHTML:NO];
        [mc setToRecipients:toRecipents];

        // Present mail view controller on screen
        [self presentViewController:mc animated:YES completion:NULL];

    }

    - (void) mailComposeController:(MFMailComposeViewController *)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError *)error
    {
        switch (result)
        {
            case MFMailComposeResultCancelled:
                NSLog(@"Mail cancelled");
                break;
            case MFMailComposeResultSaved:
                NSLog(@"Mail saved");
                break;
            case MFMailComposeResultSent:
                NSLog(@"Mail sent");
                break;
            case MFMailComposeResultFailed:
                NSLog(@"Mail sent failure: %@", [error localizedDescription]);
                break;
            default:
                break;
        }

        // Close the Mail Interface
        [self dismissViewControllerAnimated:YES completion:NULL];
    }

What I'm struggling to figure out is if I want to have the user open up the address book and send an email to one of there contacts, after the email is sent, the user has to re-open the app...and I'd like them to return to the app automatically. Below is the code for opening up the address book, viewing a contact, and either sending an email/making a call/sending a message to that contact.

- (IBAction)openContacts:(id)sender {
    ABPeoplePickerNavigationController *peoplePicker =
    [[ABPeoplePickerNavigationController alloc] init];
    peoplePicker.peoplePickerDelegate = self;
    [self presentModalViewController:peoplePicker animated:YES];
}


- (BOOL)peoplePickerNavigationController:
(ABPeoplePickerNavigationController *)picker
      shouldContinueAfterSelectingPerson:(ABRecordRef)person
{
//    [self dismissModalViewControllerAnimated:YES];
    return YES;
}

- (BOOL)peoplePickerNavigationController:
(ABPeoplePickerNavigationController *)picker
      shouldContinueAfterSelectingPerson:(ABRecordRef)person
                                property:(ABPropertyID)property
                              identifier:(ABMultiValueIdentifier)identifier
{
    return YES;
}

- (void)peoplePickerNavigationControllerDidCancel:
(ABPeoplePickerNavigationController *)picker
{
    [self dismissViewControllerAnimated:YES completion:NULL];
}

Does anyone know to have the user return straight back to the app after opening the address book? Thanks!

EDIT After implementing @Rob's suggestion, my code looks like this:

- (IBAction)openContacts:(id)sender {
    ABPeoplePickerNavigationController *peoplePicker =
    [[ABPeoplePickerNavigationController alloc] init];
    peoplePicker.peoplePickerDelegate = self;
    [self presentModalViewController:peoplePicker animated:YES];
}


- (BOOL)peoplePickerNavigationController:
(ABPeoplePickerNavigationController *)peoplePicker
      shouldContinueAfterSelectingPerson:(ABRecordRef)person
{
    return YES;
}


- (void)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker
                         didSelectPerson:(ABRecordRef)person
                                property:(ABPropertyID)property
                              identifier:(ABMultiValueIdentifier)identifier {
    if (property == kABPersonEmailProperty) {
        ABMultiValueRef emails = ABRecordCopyValue(person, property);
        CFIndex index = ABMultiValueGetIndexForIdentifier(emails, identifier);
        NSString *email = CFBridgingRelease(ABMultiValueCopyValueAtIndex(emails, index));
        CFRelease(emails);

        MFMailComposeViewController *composeViewController = [[MFMailComposeViewController alloc] init];
        [composeViewController setToRecipients:@[email]];
        composeViewController.mailComposeDelegate = self;

        [peoplePicker dismissViewControllerAnimated:NO completion:^{
            [self presentViewController:composeViewController animated:YES completion:nil];
        }];
    } else {
        [peoplePicker dismissViewControllerAnimated:YES completion:nil];
    }
}


- (void)peoplePickerNavigationControllerDidCancel:(ABPeoplePickerNavigationController *)peoplePicker {
    [peoplePicker dismissViewControllerAnimated:YES completion:nil];
}

I'm able to select a contact and either make a phone call or email, but still have to return to the app manually after completing one of these actions.

Your shouldContinueAfterSelectingPerson:property:identifier: is returning YES , which tells the people picker that you want iOS to handle the sending of the email (ie, it will leave your app). If you don't want to leave your app, have this function return NO and then present your own MFMailComposeViewController (like you showed earlier) in the appropriate ABPeoplePickerNavigationControllerDelegate function. Then you can pull up contacts and initiate the sending of an email while staying within your app.

For example, you might do something like:

#pragma mark - ABPeoplePickerNavigationControllerDelegate

// for iOS versions before 8.0

- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker
      shouldContinueAfterSelectingPerson:(ABRecordRef)person
                                property:(ABPropertyID)property
                              identifier:(ABMultiValueIdentifier)identifier {
    [self peoplePickerNavigationController:peoplePicker
                           didSelectPerson:person
                                  property:property
                                identifier:identifier];

    return NO;
}

// for iOS 8+

- (void)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker
                         didSelectPerson:(ABRecordRef)person
                                property:(ABPropertyID)property
                              identifier:(ABMultiValueIdentifier)identifier {
    if (property == kABPersonEmailProperty) {
        ABMultiValueRef emails = ABRecordCopyValue(person, property);
        CFIndex index = ABMultiValueGetIndexForIdentifier(emails, identifier);
        NSString *email = CFBridgingRelease(ABMultiValueCopyValueAtIndex(emails, index));
        CFRelease(emails);

        MFMailComposeViewController *composeViewController = [[MFMailComposeViewController alloc] init];
        [composeViewController setToRecipients:@[email]];
        composeViewController.mailComposeDelegate = self;

        [peoplePicker dismissViewControllerAnimated:NO completion:^{
            [self presentViewController:composeViewController animated:YES completion:nil];
        }];
    } else {
        [peoplePicker dismissViewControllerAnimated:YES completion:nil];
    }
}

- (void)peoplePickerNavigationControllerDidCancel:(ABPeoplePickerNavigationController *)peoplePicker {
    [peoplePicker dismissViewControllerAnimated:YES completion:nil];
}

Note, I implement the logic in the iOS 8 routine, didSelectPerson , but call it from shouldContinueAfterSelectingPerson for backward compatibility.


Unrelated to your question, but if using people picker to select email address, in iOS 8, you can keep the user from selecting contacts with no email address, as well as when showing the contact, only show the email address(es). Just a few nice iOS 8 enhancements:

ABPeoplePickerNavigationController *picker = [[ABPeoplePickerNavigationController alloc] init];
picker.peoplePickerDelegate = self;

// if you don't want user to select contacts with no email address

if ([picker respondsToSelector:@selector(setPredicateForEnablingPerson:)]) {
    picker.predicateForEnablingPerson = [NSPredicate predicateWithFormat:@"emailAddresses.@count > 0"];
}

// if you don't want to show phone numbers, mailing addresses, etc., you can show just email addresses in iOS 8

if ([picker respondsToSelector:@selector(setDisplayedProperties:)]) {
    picker.displayedProperties = @[@(kABPersonEmailProperty)];
}

[self presentViewController:picker animated:YES completion:nil];

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM