Reputation: 796
The scenario is that I have more than one view that wants to invoke the Address Book. So as not to duplicate the code of the delegate in each view I have located the code in the App Delegate's header and .m file, but using an "@interface AddressBookDelegate" and "@implementation AddressBookDelegate" at the bottom of the 2 respective App Delegate fiies-
@interface AddressBookDelegate : UIViewController <ABPeoplePickerNavigationControllerDelegate> {
AddressBookDelegate *addressBookDelegate;
}
@property (nonatomic, retain) AddressBookDelegate *addressBookDelegate;
@end
and
@implementation AddressBookDelegate
@synthesize addressBookDelegate;
- (void)peoplePickerNavigationControllerDidCancel: (ABPeoplePickerNavigationController *)peoplePicker
{
[self dismissModalViewControllerAnimated:YES];
}
- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person
{
[super dismissModalViewControllerAnimated:YES];
...get stuff from the Address Book...
return NO;
}
- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person
property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier
{
return NO;
}
Then in my views I have the following code:
addressBookDelegate = (AddressBookDelegate *) [[UIApplication sharedApplication] delegate];
ABPeoplePickerNavigationController *abPicker = [[ABPeoplePickerNavigationController alloc]init];
abPicker.peoplePickerDelegate = self.addressBookDelegate;
[self presentModalViewController:abPicker animated:YES];
[abPicker release];
The Address Book displays fine in all views. But when I take any user action that would invoke a delegate, like the Address Book's Cancel button, I crash-
-[MyprogAppDelegate peoplePickerNavigationControllerDidCancel:]: unrecognized selector sent to instance
It compiles clean, no Warnings.
How do I wire-up the peoplePickerDelegate to connect to the Address Delegate code when it is not physically in the same file as the view itself ? Thx.
ADDED NOTE: when I use the debugger and stop on the line
abPicker.peoplePickerDelegate = addressBookDelegate;
in the view code, I see that the address for the addressBookDelegate is stated to be the address of the MyprogAppDelegate, not AddressBookDelegate as I might have expected. That makes me think the displacement to the address book delegate code is off within the App Delegate file.
If the AddressBookDelegate Cancel Delegate code were say 1000 bytes into the AddressBookDelegate, my app is actually "entering" the code 1000 bytes into MyprogAppDelegate, and so crashes. So somehow I am not setting up the addressing of the AddressBookDelegate correctly. That's my take on it anyway...
Upvotes: 0
Views: 1054
Reputation: 796
In the end I was not able to make any of the above suggestions perform as hoped for. I had to cut time and move on so I duplicated the code in each view. I will revisit this another time, as I am sure it can be done in a more object based way than I ended it doing it.
Upvotes: 0
Reputation: 678
EDIT Okay, the entire first answer has been tossed out. This is, with some warning, still a bit of a shot in a dark, but I think it's going to be closer to helpful. Some of the ideas do carry over though.
You very probably don't need a separate class to act as your ABPeoplePickerNavigationControllerDelegate
. In all likelihood, it should be the same class that has your code at the bottom (that calls presentModalViewController:animated:
. Since I don't know what controller that was, I'm going to just call it MyViewController
for reference. The reason you want that view controller to be the delegate is because, in your delegate methods, you need to be able to dismiss the modal view controller that has the address book.
You definitely don't want the your program's UIApplicationDelegate
to be the ABPeoplePickerNavigationControllerDelegate
. As you said yourself, peoplePickerDelegate
has to be a UIViewController
.
So, to MyViewController
. First, the interface:
/* MyViewController.h */
@interface MyViewController : UIViewController<ABPeoplePickerNavigationControllerDelegate>
...
@end
Your controller might inherit from a descendant of UIViewController (like a table view controller or something like that) - that shouldn't change, the only thing that should change is adding the ABPeoplePickerNavigationControllerDelegate
to the list of implemented protocols.
Now, to implement the functionality:
/* MyViewController.m */
@implementation MyViewController
...
- (void) whateverMethodIsDisplayingTheAddressBook
{
ABPeoplePickerNavigationController *abPicker = [[ABPeoplePickerNavigationController alloc]init];
abPicker.peoplePickerDelegate = self; // This view controller is the delegate
[self presentModalViewController:abPicker animated:YES];
[abPicker release];
}
...
- (void)peoplePickerNavigationControllerDidCancel: (ABPeoplePickerNavigationController *)peoplePicker
{
[self dismissModalViewControllerAnimated:YES];
}
- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker
shouldContinueAfterSelectingPerson:(ABRecordRef)person
{
[super dismissModalViewControllerAnimated:YES];
...get stuff from the Address Book...
return NO;
}
- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker
shouldContinueAfterSelectingPerson:(ABRecordRef)person
property:(ABPropertyID)property
identifier:(ABMultiValueIdentifier)identifier
{
return NO;
}
@end
Upvotes: 0
Reputation: 29767
Your code assumes that your appdelegate (MyprogAppDelegate) implements method peoplePickerNavigationControllerDidCancel
.
So, your code in MyprogAppDelegate should be something like this:
@implementation MyprogAppDelegate
@synthesize ...;
#pragma mark -
#pragma mark Application lifecycle
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
return YES;
}
- (void)peoplePickerNavigationControllerDidCancel:(ABPeoplePickerNavigationController *)peoplePicker{
}
Upvotes: 1