views:

1256

answers:

2

I have two Objective-C classes that inherit from the UIViewController and am trying a different approach at learning how to interact with the iPhone's address book. The example Apple provides assumes that everything is in one class, but this isn't the way I need it done. My objective would be to have the address book view close after a person is selected. Please have a look and let me know how i can accomplish this without having CallerClass implement ABPeoplePickerNavigationControllerDelegate. Thanks!

-- edit --

What it seems to be boiling down to is the [self dismissModalViewControllerAnimated:YES]; does not have any effect in CalleeClass.m. I still can't seem to get a reaction to close the address book from this command.

CallerClass.m

#import "CallerClass.h"

@implementation CallerClass
- (IBAction)openAddressBook {
    CalleeClass *cc = [[CalleeClass alloc] init];
    [self presentModalViewController:[cc doIt] animated:YES];
}

CalleeClass.h

#import <UIKit/UIKit.h>
#import <AddressBook/AddressBook.h>
#import <AddressBookUI/AddressBookUI.h>

@interface CalleeClass : UIViewController <ABPeoplePickerNavigationControllerDelegate> {
    NSString *name;
}

-(ABPeoplePickerNavigationController *)doIt;

@property (nontoxic, retain) NSString *name;

@end

CalleeClass.m

#import <UIKit/UIKit.h>
#import <AddressBook/AddressBook.h>
#import <AddressBookUI/AddressBookUI.h>
#import "CalleeClass.h"

@implementation CalleeClass
@synthesize name;

… (default ABPeoplePickerNaviationControllerDelegate implementation outside of what's listed)

- (id)initWithFrame:(CGRect)frame {
    if (self = [super initWithFrame:frame]) {}
    return self;
}

- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person {
    self.name = (NSString *)ABRecordCopyValue(person,kABPersonAddressProperty);

    [self dismissModalViewControllerAnimated:YES];
    return NO; 
}

-(ABPeoplePickerNavigationController *)doIt {
    ABPeoplePickerNavigationController *picker = [[ABPeoplePickerNavigationController alloc] init];
    picker.peoplePickerDelegate = self;
    return picker;
}

@end
A: 

Once you have identified the contact you want to act on you can just pass around the int32 recordID, although as mentioned in the API docs you should probably also use the composite name since as you will notice the recordID is a simple value that starts with "1" and you could run into trouble if your database was restored to a phone with new contacts in old recordID values. Every time you need to access something from the Address Book you do need to create the phone book but you can close it right after, so with recordID you can open, get what you want and then close it. My suggestion is just use the picker like a normal view controller up to the point where you get the recordID, dismiss it, then keep that unique identifier. Use picker again when you need to find a new recordID.

Adam Eberbach
I am acting on it with self.name = (NSString*)ABRecordCopyValue(person,kABPersonAddressProperty);I was hoping after I acted on it, I would be able to close the address book with:[self dismissModalViewControllerAnimated:YES];but that doesn't appear to be the case.The whole intention of this post is to NOT use the picker as a normal controller but rather as the fashion above. I basically need to extract data on a one-time basis and never reference it again, so having a portable identifier does not concern me.
Mat
+1  A: 

If the problem is, as you say, that [self dismissModalViewControllerAnimated:YES] has no effect if called from CalleeClass, this is because dismissModalViewControllerAnimated: must be called on the presenting view controller (i.e., the one on which you called presentModalViewController:Animated:. Since you don't have a reference to your CallerClass instance in CalleeClass, this doesn't work.

Fortunately, as the documentation for dismissModalViewControllerAnimated: notes:

If you call this method on the modal view controller itself, however, the modal view controller automatically forwards the message to its parent view controller.

So this should work:

- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person {
    self.name = (NSString *)ABRecordCopyValue(person,kABPersonAddressProperty);
    [peoplePicker dismissModalViewControllerAnimated:YES];
    return NO;  
}
Ole Begemann