19

2010 年 9 月 2 日更新:此代码在 iOS 4 更新后不再有效 - 它因内部断言而失败。现在在 iPhone SDK 参考库中提供了一个很棒的地址簿 API 示例,称为“QuickContacts”。

示例代码可在此处获得;它将帮助您解决这个问题:http: //developer.apple.com/iphone/library/samplecode/QuickContacts/Introduction/Intro.html


我正在尝试向我的应用程序添加一项功能,该功能允许用户从ABPeoplePickerNavigationController中选择联系人,然后显示与他们选择的联系人相对应的ABPersonViewController 。那时,我希望用户能够单击联系人的电话号码并让我的应用程序以自定义行为响应。

我的ABPeoplePickerNavigationController工作正常,但在显示ABPersonViewController时遇到问题。我可以让ABPersonViewController很好地在屏幕上显示动画,但它只显示联系人的照片、姓名和公司名称。不显示联系人的其他字段。

我使用ABPersonViewController中的“displayedProperties”元素来告诉程序显示电话号码。这会产生一些奇怪的行为;当我选择没有分配电话号码的联系人时,联系人会在背景中写入“无电话号码”(如您所期望的),但在选择有电话号码的联系人时,我得到的就是一个空白的联系页面(没有“无电话号码”文本)。

这是我用来创建我的PersonViewController类的ABPeoplePickerNavigationController 委托类中的方法,该类实现了ABPersonViewController 接口:

- (BOOL) peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person {

    BOOL returnState = NO;

    PersonViewController *personView = [[PersonViewController alloc] init];
    [personView displayContactInfo:person];

    [peoplePicker pushViewController:personView animated:YES];

    [personView release];

    return returnState;
}

这是我的PersonViewController.h头文件:

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

@interface PersonViewController : UIViewController <ABPersonViewControllerDelegate> 
{

}

- (void) displayContactInfo: (ABRecordRef)person;

@end

最后,这是我的PersonViewController.m,它正在创建ABPersonViewController以查看所选联系人:

#import "PersonViewController.h"

@implementation PersonViewController

- (void) displayContactInfo: (ABRecordRef)person
{
    ABPersonViewController *personController = [[ABPersonViewController alloc] init];

    personController.personViewDelegate = self;
    personController.allowsEditing = NO;
    personController.displayedPerson = person;
    personController.addressBook = ABAddressBookCreate();

    personController.displayedProperties = [NSArray arrayWithObjects:
            [NSNumber numberWithInt:kABPersonPhoneProperty], 
            nil];

    [self setView:personController.view];

    [[self navigationController] pushViewController:personController animated:YES];
    [personController release];
}

- (BOOL) personViewController:(ABPersonViewController*)personView shouldPerformDefaultActionForPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifierForValue
{
    return YES;
}


@end

有谁知道为什么我看到这个空白的联系人屏幕而不是带有可点击电话号码字段的屏幕?


好吧,我想我离发现问题越来越近了。我相当确定它与上面 displayContactInfo 调用的这一部分有关:

[self setView:personController.view];

当我省略这一行时,当我点击一个联系人时,我看到的只是一个空白屏幕。ABPeoplePickerNavigationController 将 PersonViewController 推送到 NavigationController 堆栈上。PersonViewController 然后实例化一个 ABPersonViewController 对象,但无论出于何种原因,ABPersonViewController 永远不会正确添加到 NavigationController 堆栈中。

有谁知道如何将 ABPersonViewController 添加到堆栈中,而不仅仅是 PersonViewController?

4

1 回答 1

9

对任何自己遇到此问题的人的提醒:我能够通过在其委托的viewDidLoad()方法中实例化 ABPersonViewController 来产生正确的行为,如下所示:

和以前一样,这是我的ABPeoplePickerNavigationController 委托的方法:

- (BOOL) peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person
{
    BOOL returnState = NO;

    PersonViewController *personView = [[PersonViewController alloc] init];

    [peoplePicker pushViewController:personView animated:YES];
    [personView displayContactInfo:person];

    [personView release];

    return returnState;
}

这是我的 PersonViewController.h(ABPersonViewController 委托)头文件:

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

@interface PersonViewController : UIViewController <ABPersonViewControllerDelegate> 
{
    ABPersonViewController *personController;
}

- (void) displayContactInfo: (ABRecordRef)person;

@end

最后,这是委托的实现(PersonViewController.m):

#import "PersonViewController.h"

@implementation PersonViewController

- (void) viewDidLoad
{
}

- (void) viewDidUnload
{
    [personController release];
}

- (void) displayContactInfo: (ABRecordRef)person
{
    personController = [[ABPersonViewController alloc] init];
    [personController setDisplayedPerson:person];
    [personController setPersonViewDelegate:self];
    [personController setAllowsEditing:NO];
    personController.addressBook = ABAddressBookCreate();   

    personController.displayedProperties = [NSArray arrayWithObjects:
        [NSNumber numberWithInt:kABPersonPhoneProperty], 
        nil];

    [self setView:personController.view];
}

- (BOOL) personViewController:(ABPersonViewController*)personView shouldPerformDefaultActionForPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifierForValue
{
    // This is where you pass the selected contact property elsewhere in your program
    [[self navigationController] dismissModalViewControllerAnimated:YES];
    return NO;
}

@end

Hopefully this ends up being helpful for someone. The AddressBook UI framework was a bit tricky for me to wrap my head around (although I'm new to iPhone development so I'm still learning a lot of the nuances of iPhone program organization).

于 2009-08-31T07:17:21.377 回答