views:

1283

answers:

3

Hey,

I am presenting an ABPeoplePickerNavigationController to the user and asking them to select a contact. Once they select a user, I want to have them sent to either the Messages app or the Email app depending on what property they selected. However, I can't figure out how to customize the action that occurs after the modal picker is dismissed.

- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier {
    if(property == kABPersonPhoneProperty){
        [self dismissModalViewControllerAnimated:YES];
        NSString* phoneNumber = (NSString *)ABRecordCopyValue(person, property);
        NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"sms:%@", phoneNumber]];
        [[UIApplication sharedApplication] openURL:url];
        [phoneNumber release];
        return NO;
    }

    if(property == kABPersonEmailProperty){
        [self dismissModalViewControllerAnimated:YES];
        NSString* emailAddress = (NSString *)ABRecordCopyValue(person, property);
        NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"mailto:%@", emailAddress]];
        [[UIApplication sharedApplication] openURL:url];
        [emailAddress release];
        return NO;
    }
    return YES;
}

So, how do I do this? Thanks!

A: 

You could create a custom protocol with two methods (say, pickedPhone and pickedMail) and have the class calling this one implement those routines and assign itself as the delegate. Once the decision has been made, you check to see if the delegate is defined then invoke the right method and let the caller handle what to do with it.

Also, you should do some testing on the "sms" url. Last I checked it runs the SMS app but doesn't pass anything to it.

But before you even get there, the way you have it now by calling those openURLs to invoke external Phone or Email apps, your app will be stopped and control will be transferred to those apps. So I'm not sure why you care what happens after the user dismisses the modal picker because your app will no longer be around.

Now under OS 3.0 you may have some options, but still... you may want to reconsider the problem.

Ramin
I am aware that my app will lose control. I'm trying to intercept the property selection in order to customize the email that gets opened up. I can set the subject/body for the user as a matter of convenience. Also, if they select a phone number, I want the SMS app to show up, not the Phone app. Thus, I need to intercept it and then call the appropriate openURL.
Georges
+1  A: 

You need simply to implement the delegate method

   - (BOOL)personViewController:(ABPersonViewController *)personViewController shouldPerformDefaultActionForPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifierForValue

In the implementation simply return YES (unless you need to process the selected property). Then, if the user touched a phone number, your app will start calling that phone number. Similarly, if the user touched an email address, yout app will switch to the default compose email view.

Do not forget to assign yourself as the delegate, otherwise the mthod will not be called:

ABPeoplePickerNavigationController *peoplePicker = [[ABPeoplePickerNavigationController alloc] init];
peoplePicker.peoplePickerDelegate = self;
[self presentModalViewController:peoplePicker animated:YES];

And finally, put ABPeoplePickerNavigationControllerDelegate in the protocol section of your controller's header file.

NOTE: you should test this on the device, not on the simulator.

unforgiven
Thanks for the response.I'm a bit confused, though, because the method you suggested I implement is in the ABPersonViewControllerDelegate protocol, not the PeoplePicker protocol. I've set my controller as the delegate for the ABPeoplePickerNavigationController and those methods are being called properly, but the ABPersonViewController delegate method is never getting called. I assume this is because I haven't set my controller as the delegate for the ABPersonViewControllers that are being instantiated by the ABPeoplePickerNavigationController. Do you know how to set that up?
Georges
Once the user selects a contact, you simply need to init/alloc an ABPersonViewController set its delegate and person to be shown (the contact selected by your user), then push it on the stack. Then, when clicking on a phone number or email address, the default action will be triggered.
unforgiven
A: 

Solved. The problem was not with the delegate methods. It was that the NSURL I am creating is invalid. To launch the SMS/Messaging app with the selected phone number, user sms:// ... the // is key! The docs seem to indicate sms: as the correct format, but I have found that that is incorrect.

Georges