3

以下代码在 iOS7 中正常工作,但在 iOS8 中不正常(变量recordID设置正确):

    CFErrorRef error = nil;
    const ABAddressBookRef addressBook = (ABAddressBookCreateWithOptions (NULL, &error));
    ABRecordRef contactRef = ABAddressBookGetPersonWithRecordID (addressBook, recordID);
    ABPersonViewController *personViewController = [[ABPersonViewController alloc] init];
    personViewController.addressBook     = addressBook;
    personViewController.displayedPerson = contactRef;
    CFRelease(addressBook);
    NSArray *displayedProperties = @[@(kABPersonFirstNameProperty),
                                     @(kABPersonLastNameProperty),
                                     @(kABPersonMiddleNameProperty),
                                     @(kABPersonPrefixProperty),
                                     @(kABPersonSuffixProperty),
                                     @(kABPersonOrganizationProperty),
                                     @(kABPersonJobTitleProperty),
                                     @(kABPersonDepartmentProperty),
                                     @(kABPersonEmailProperty),
                                     @(kABPersonBirthdayProperty),
                                     @(kABPersonKindProperty),
                                     @(kABPersonAddressProperty),
                                     @(kABPersonPhoneProperty),
                                     @(kABPersonInstantMessageProperty),
                                     @(kABPersonURLProperty),
                                     @(kABPersonSocialProfileProperty),
                                     @(kABPersonNoteProperty)];
    personViewController.displayedProperties  = displayedProperties;
    personViewController.navigationItem.title = NSLocalizedString(@"CONTACT_DETAILS", nil);
    personViewController.allowsActions        = YES;
    personViewController.allowsEditing        = YES; // if NO, no back button is shown
    personViewController.personViewDelegate   = self;
    personViewController.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"ADDRESSES",nil) style:UIBarButtonItemStylePlain target:self action:@selector(personviewDoneButtonPressed:)];

    UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:personViewController];
    [self presentViewController:navigationController animated:YES completion:nil];

iOS8 中的错误:

  1. allowsEditing设置为YES时,会显示联系人,但 仅显示姓名。导航栏左侧显示后退按钮(名为“地址”),右侧显示编辑按钮。按下编辑按钮时,联系人显示为除姓名以外的所有字段为空,并且编辑按钮显示为完成按钮。如果在未进行任何编辑的情况下按下此完成按钮,则会显示有关联系人的所有信息,则会显示有关联系人的所有信息。
  2. allowsEditing设置为 时,NO不显示返回按钮,从而无法再离开屏幕。

有人有解决方法吗?

更新:

我现在意识到,问题 1有时只发生在模拟器上,尽管总是 在我的设备上

4

2 回答 2

5

montuno(再次感谢),他评论了我的第一个答案,从 Apple 技术支持那里得到了如何解决第一个问题的提示,我现在也理解了第二个问题:

1) 只显示部分联系人:

苹果声称以下代码是错误的:

ABRecordRef contactRef = ABAddressBookGetPersonWithRecordID (addressBook, recordID);
ABPersonViewController *personViewController = [[ABPersonViewController alloc] init];
personViewController.addressBook     = addressBook;
personViewController.displayedPerson = contactRef;
CFRelease(addressBook);

addressBook它被分配给ABPersonViewController.

在我的原始代码中,我没有CFRelease声明。但随后静态分析器警告“地址簿中存储的对象可能发生泄漏”。在我插入发布声明后,构建成功而没有警告,所以我假设personViewController保留了addressBook,这显然不是这种情况,至少在 iOS8 中不是这样。我现在再次删除了发布声明,收到了警告,但一切正常。

2) 缺少后退按钮:
文档中ABPersonViewController说“<em>重要的人视图控制器必须与导航控制器一起使用才能正常运行。”

所以我做了以下事情:
我设置了一个ABPersonViewController,分配给它navigationItem.backBarButtonItem一个“<em>Done”按钮,并UINavigationController用这个初始化一个新的personViewController,使用initWithRootViewController:. 然后我介绍了新的navigationController模态。
显示personViewController带有后退按钮的按钮,当按下时,呈现视图控制器关闭模态呈现的导航控制器。
这在 iOS < 8 上运行良好,但在 iOS8 中,当allowsEditing设置为NO.

但这显然不是 Apple 想要显示的方式personViewController
我认为 Apple 假设 anavigationController已经存在,并呈现当前视图,以便将 newpersonViewController推送到navigationController. 在这种情况下,personViewController不是rootViewControllernavigationController并且navigationController会自动显示一个后退按钮(对于 没有这样做rootViewController)。如果以这种方式实现,iOS8 也可以正常工作。

于 2014-11-20T07:17:15.213 回答
0

更新:这个黑客不再起作用并且完全没用(见我的新答案)

如果有人遇到上述相同的问题 1),这是一个非常肮脏的解决方法,直到 Apple 修复错误(我的错误报告仍然打开):
因为在某些情况下需要在ABPersonViewController屏幕显示后切换两次编辑按钮,可以以编程方式执行此操作:

为 定义一个UINavigationController显示的属性ABPersoViewController

@property (nonatomic, strong) UINavigationController *  navigationControllerForPersonViewController;

在导航控制器呈现人员视图控制器后,执行选择器来进行切换:

[self performSelector:@selector(toggleEditButton) withObject:nil afterDelay:0.7];  

设置延迟以便人员视图控制器屏幕可以出现动画。该方法toggleEditButton定义为:

- (void)toggleEditButton
{
    UIBarButtonItem *editButton  = self.navigationControllerForPersonViewController.topViewController.navigationItem.rightBarButtonItem;
    id target = editButton.target;
    SEL editAction = editButton.action;
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
    [target performSelector:editAction withObject:editButton];
    [target performSelector:editAction withObject:editButton];
#pragma clang diagnostic pop
}

需要#pragmas 来抑制潜在内存泄漏的编译器警告。
结果是人视图控制器的所有选择信息都实际显示出来了。

于 2014-10-18T09:28:50.363 回答