让 ABPeoplePickerNavigationController 像联系人应用程序一样工作是不是太复杂了?
我试图让 ABPeoplePickerNavigationController 像联系人应用程序一样工作,但发现它太复杂了。我不确定这是因为我做错了还是事情就是这样。
第一个任务是删除右侧栏按钮上的“取消”按钮。以下代码不起作用!
picker.navigationItem.rightBarButtonItem = nil;
我困惑了一段时间,然后发现这是因为取消rightBarButtonItem属于ABPeoplePickerNavigationController包含的子视图,例如ABPersonViewController,但不是ABPeoplePickerNavigationController本身!这就是原因。很容易验证,只要打印出picker.navigationItem.rightBarButtonItem,它就一直是nil。
所以我实现了ABPeoplePickerNavigationController.delegate(而不是peoplePickerDelegate)。但在实现它时需要一些技巧,这就是我的问题。
所以先写代码:
#pragma mark UINavigationControllerDelegate methods
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
switch ([navigationController.viewControllers count]) {
case 1:
viewController.navigationItem.rightBarButtonItem = nil;
break;
case 2: {
UIBarButtonItem *addButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(addButtonClicked)];
[viewController.navigationItem setRightBarButtonItem:addButtonItem animated:NO];
[addButtonItem release];
break;
}
case 3: {
UIBarButtonItem *editButtonItem;
if ([viewController isKindOfClass:[ABPersonViewController class]]) {
editButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemEdit target:self action:@selector(editButtonClicked:)];
self.personView = (ABPersonViewController*) viewController;
self.personView.allowsEditing = YES;
[viewController.navigationItem setRightBarButtonItem:editButtonItem animated:NO];
[editButtonItem release];
} else {
//ABPersonNewViewController
//No need to add codes here
}
break;
}
default: {
UIBarButtonItem *cancelButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:@selector(addButtonClicked)];
[viewController.navigationItem setRightBarButtonItem:cancelButtonItem animated:NO];
[cancelButtonItem release];
break;
}
}
}
这里的第一个奇怪的事情是,当 ABPeoplePickerNavigationController 仅包含 1 或 2 个子视图时,即此处的情况 1 和情况 2,viewController 分别是 ABAccountsAndGroupsViewController、ABMembersViewController。
ABAccountsAndGroupsViewController 和 ABMembersViewController 不是 AddressBookUI 的公共 API,因此我无法直接访问它们(我通过打印它们的名称来获取它们)。这就是为什么我检查 viewControllers 的计数。所以我的第一个问题是为什么苹果不公开 API?
第二个问题是关于ABPersonViewController(案例3)。如果是ABNewPersonViewController,其navigationItem可以正确显示“取消”和“完成” UIBarButtonItem。我不需要在那里做任何事情。
但如果是 ABPersonViewController,“取消”UIBarButtonItem 仍显示为 rightBarButtonItem 而不是 Edit 按钮(即使我已将 allowedEditing 设置为 YES )。所以我必须手动设置它。但为什么 ??有更好的方法吗?
有没有比我在这里编写的代码更好的方法来使 ABPeoplePickerNavigationController 像联系人应用程序一样工作?
谢谢!
I am trying to make ABPeoplePickerNavigationController work like Contact App and find it is way too complicated. I am not sure if this is because I have done it wrong or it is just the way it is.
The first task is to get rid of Cancel button at right bar button. The following code does NOT work!
picker.navigationItem.rightBarButtonItem = nil;
I was confused for a while then found out that it is because the Cancel rightBarButtonItem belongs to the subview ABPeoplePickerNavigationController contains, e.g. ABPersonViewController, but NOT ABPeoplePickerNavigationController itself! And this is the reason. It is easy to verify that, just print out picker.navigationItem.rightBarButtonItem, it is nil all the time.
So I implement ABPeoplePickerNavigationController.delegate (not peoplePickerDelegate). But it took quite some tricks in implementing it and that comes my questions.
So code first:
#pragma mark UINavigationControllerDelegate methods
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
switch ([navigationController.viewControllers count]) {
case 1:
viewController.navigationItem.rightBarButtonItem = nil;
break;
case 2: {
UIBarButtonItem *addButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(addButtonClicked)];
[viewController.navigationItem setRightBarButtonItem:addButtonItem animated:NO];
[addButtonItem release];
break;
}
case 3: {
UIBarButtonItem *editButtonItem;
if ([viewController isKindOfClass:[ABPersonViewController class]]) {
editButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemEdit target:self action:@selector(editButtonClicked:)];
self.personView = (ABPersonViewController*) viewController;
self.personView.allowsEditing = YES;
[viewController.navigationItem setRightBarButtonItem:editButtonItem animated:NO];
[editButtonItem release];
} else {
//ABPersonNewViewController
//No need to add codes here
}
break;
}
default: {
UIBarButtonItem *cancelButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:@selector(addButtonClicked)];
[viewController.navigationItem setRightBarButtonItem:cancelButtonItem animated:NO];
[cancelButtonItem release];
break;
}
}
}
The first weird thing here is that when ABPeoplePickerNavigationController only contains 1 or 2 subviews, case 1 and case 2 here, the viewController is ABAccountsAndGroupsViewController, ABMembersViewController respectively.
ABAccountsAndGroupsViewController and ABMembersViewController are not the public API for AddressBookUI, so I can't to access them directly (I got them by print out their names). That is why I check viewControllers's count instead. So my first question is why doesn't Apple them public API ?
The second question is about ABPersonViewController (Case 3). If it is ABNewPersonViewController, its navigationItem can correctly show the "Cancel" and "Done" UIBarButtonItem. I do not need to do anything there.
But if it is ABPersonViewController, the "Cancel" UIBarButtonItem still show as rightBarButtonItem instead of Edit Button (even I have set allowsEditing to YES ). So I have to set it manually. But why ?? Is there is better way to do it?
And is there any better way than the code I wrote here to make ABPeoplePickerNavigationController work like Contact App?
Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
升级到iOS 5后我发现代码需要一些修改。
当 ABPeoplePickerNavigationController 显示 ABAccountsAndGroupsViewController(情况 1)时,这些现在是左侧的刷新栏按钮。我不确定这是否用于从交换服务器同步联系人或它将触发什么操作?
但是如果我用我自己的刷新按钮替换默认按钮,我的操作将不会被调用!而且我发现它只发生在ABAccountsAndGroupsViewController上,其他情况仍然有效!
因此,为了让我的代码在 iOS 5 中工作,我必须实现委托方法 didShowViewController 而不是 willShowViewController
After upgraded to iOS 5 I find the code needs some modification.
When ABPeoplePickerNavigationController shows ABAccountsAndGroupsViewController (case 1), these is now a refresh bar button on the left. I am not sure if that is used to sync contacts from exchange server or what action it will trigger ?
But if I substitute the default button with my own refresh button, my action won't be called! And I find that it only happens to ABAccountsAndGroupsViewController, other cases still work!
So to make my codes work in iOS 5, I have to implemented delegate method didShowViewController NOT willShowViewController