ABUnknownPersonViewController

The ABUnknownPersonViewController class is a handy way to prompt users to find records in, or add records to, the iPhone address book from within your application. Unfortunately, it’s not the most intuitive thing to code for. Today, I present a brief guide to integrating this controller into your application.

Non-Modal

The ABUnknownPersonViewController documentation states clearly that:

Important: Unknown-person view controllers must be used inside of a navigation controller in order to function properly.

Given this, and given that the operation that the user is performing is a modal one, you might be tempted to present the controller inside it’s own navigation controller, with something along these lines:

ABUnknownPersonViewController* abNew = [[ABUnknownPersonViewController alloc] init];

// Configure abNew
// …

UINavigationController* nc = [[UINavigationController alloc] initWithRootViewController:abNew];
[self.navigationController presentModalViewController:nc animated:YES];
[nc release];

[abNew release];

This code assumes that it is executed from within a method of a view controller on a navigation controller stack, hence the self.navigationController business.

Do not do this!. Presenting the ABUnknownPersonViewController modally will give rise to endless problems later on. Instead, it must be pushed onto the navigation controller’s stack as a non-modal view. (On this point I differ with other sources on the Internet, but since none of the sources I found presented working code, I’m going with my interpretation.)

Proper setup of an ABUnknownPersonViewController looks like this:

- (void)presentUnknownDialogForFirstName:(NSString*)firstName lastName:(NSString*)lastName
{
	ABRecordRef personRef = ABPersonCreate();
	ABUnknownPersonViewController* abNew = [[ABUnknownPersonViewController alloc] init];
		
	CFErrorRef err = nil;	// Should be released if set?
	ABRecordSetValue(personRef, kABPersonFirstNameProperty, (CFStringRef)firstName, &err)	&&
	ABRecordSetValue(personRef, kABPersonLastNameProperty, (CFStringRef)lastName, &err)	;
		
	NSString* msg = @"A unique address book entry could not be found for %@; Please create a new record, or select one from the address book.";
		
	abNew.message = [NSString stringWithFormat:msg,firstName];
	abNew.displayedPerson = personRef;
	abNew.addressBook = self.addressBook;
	abNew.allowsActions = NO;
	abNew.allowsAddingToAddressBook = YES;
	abNew.unknownPersonViewDelegate = self;
	[self.navigationController pushViewController:abNew animated:YES];
		
	[abNew release];
	CFRelease(personRef);
}

This code assumes that it is a method of a view controller on a navigation controller stack. It further assumes that its view controller has an addressBook property that returns an ABAddressBookRef, and adopts the ABUnknownPersonViewControllerDelegate protocol.

Delegate

You really only need to implement one method of the unknown person controller’s delegate:

- (void)unknownPersonViewController:(ABUnknownPersonViewController*)unknownPersonView didResolveToPerson:(ABRecordRef)personRef
{
	if (personRef)
	{
		[self.navigationController popViewControllerAnimated:NO];

		// Do something with the person record
		// ...
	}
}

A few things to note here:

  1. This code is not executed if the user just hits the “back” button to pop the unknown person controller off the stack; that’s fine, that’s what you want.
  2. The personRef might be NULL (if the user started to add a new person to the address book, and then cancelled) or non-NULL (if the user either selected an existing record, or created a new one).
  3. The unknown person controller offers the user a choice to either create a new user, or select an existing one; when the user makes this choice, the unknown person controller presents its own modal view; this view is always being displayed when this delegate method is invoked.
  4. After this delegate method is invoked, the unknown person controller will dismiss its own modal view; you do not need to, and should not, attempt to do this yourself.
  5. Instead, you should pop the unknown person controller off its navigation stack without animation; that way, when the displayed modal view is dismissed, the original view controller (from which the user requested the unknown person controller) will be revealed.

Not that hard, but not that well documented, either.

Share and Enjoy:
  • Twitter
  • Facebook
  • Digg
  • Reddit
  • HackerNews
  • del.icio.us
  • Google Bookmarks
  • Slashdot
This entry was posted in iPhone. Bookmark the permalink.

Comments are closed.