ABPeoplePickerNavigationController - remove “Cance

2019-05-01 03:57发布

问题:

I'm using the ABPeoplePickerNavigationController, a subclass of UINavigationController, and in the context I'm using it the default nav bar button for the right side, "Cancel", makes no sense. I can't find a way to disable or hide it, and whatever method used needs to be public and store-approvable. Getting rid of the nav bar entirely (picker.navigationBarHidden = YES;) might be an option except that after popping back to the list of contacts the nav bar reappears. Subclassing ABPeoplePickerNavigationController and intercepting viewWillAppear to try and nil the cancel button did not work. [picker setAllowsCancel:NO]; DOES work but is undocumented so I expect would never pass approval.

回答1:

this one

- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
  UIView *custom = [[UIView alloc] initWithFrame:CGRectMake(0.0f,0.0f,0.0f,0.0f)]; 
  UIBarButtonItem *btn = [[UIBarButtonItem alloc] initWithCustomView:custom]; 
  //UIBarButtonItem *btn = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(addAction)]; 
  [viewController.navigationItem setRightBarButtonItem:btn animated:NO]; 
  [btn release]; 
  [custom release]; 
}

works perfect!



回答2:

The examples herein using the delegate method navigationController:willShowViewController:animated: do work, but it may be the case that you want to add your own navigation item in your own controllers and the given options will remove anything that you might set in your own controllers. Here's code that I've successfully used to get this option to work well:

- (void)navigationController:(UINavigationController *)navigationController
      willShowViewController:(UIViewController *)viewController
                    animated:(BOOL)animated {

    // Here we want to remove the 'Cancel' button, but only if we're showing
    // either of the ABPeoplePickerNavigationController's top two controllers
    if ([navigationController.viewControllers indexOfObject:viewController] <= 1) {

        viewController.navigationItem.rightBarButtonItem = nil;
    }
}

Note that there are two view controllers in the navigation controller's stack, the one for contact groups and one for the contact list. This is why we cannot just check fi the viewController is the navigation controller's top view controller.



回答3:

There is no answer to this - write a new person picker if you can't live with the cancel.



回答4:

You can achieve that result browsing through the picker subviews. Just a little boring...



回答5:

I haven't tried it yet, but I think Uby is saying to iterate through the subviews of the picker until you find one that is isKindOfClass:[UIBarButtonItem class] and then you can change it's title property. It might also be in the navigationBar's 'Item' array.



回答6:

Set delegate to PeoplePickerController controller. In the delegate class, have this delegate method.

- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
 UIView *pCustomView = [[UIView alloc] initWithFrame:CGRectMake(0,0,0,0)];
 UIBarButtonItem *pBtn = [[UIBarButtonItem alloc] initWithCustomView:pCustomView];
 [viewController.navigationItem setRightBarButtonItem:pBtn animated:NO];
 [pBtn release];
 [pCustomView release];
}


回答7:

Be sure to set the delegate for picker object (not the peoplePickerDelegate, just the delegate) to the class that implement the following method:

- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
UIView *custom = [[UIView alloc] initWithFrame:CGRectMake(0,0,0,0)];
UIBarButtonItem *btn = [[UIBarButtonItem alloc] initWithCustomView:custom];
[viewController.navigationItem setRightBarButtonItem:btn animated:NO];
[btn release];
[custom release];
} 


回答8:

It works fine but in iOS 4 there is one more thing. When I switch back to my app using Fast App Switching feature, the cancel button appears again.

The method

- (void)navigationController:(UINavigationController *)navigationController  
      willShowViewController:(UIViewController *)viewController
                    animated:(BOOL)animated

doesn't get called. So I made this:

- (void)applicationDidEnterBackground:(UIApplication *)application {
    id topView = pickerControllerDelegate.peoplePicker.topViewController;
    topView.navigationItem.rightBarButtonItem = nil;
}

It works pretty well.



回答9:

according to russel b you could just overwrite your viewdidapper

this worked for me:

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    UINavigationItem *item = (UINavigationItem *)[self.navigationBar.items lastObject];
    item.rightBarButtonItems = [[NSArray alloc] init];

    item.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(addPerson)];
}


回答10:

EDIT: See comments below. This is now an illustration of what not to do.

I tried to get the desired behavior with the public API by subclassing ABPeoplePickerNavigationController and intercepting all the events that change the current navigation view controller view. Then one can just navigate the view hierarchy and purge all the unwanted buttons.

You can navigate the view hierarchy from a delegate, but you aren't privy to the events that change the view state... which makes it hard to kill the Cancel button and make it stick.

This code kind of worked for me (NOTE: it brute-force kills all the right-hand buttons):

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    [self killCancelButton];
}

- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated {
    [super pushViewController:viewController animated:animated];
    [self killCancelButton];
}

- (UIViewController*)popViewControllerAnimated:(BOOL)animated {
    UIViewController *result = [super popViewControllerAnimated:animated];
    [self killCancelButton];
    return result;
}

- (void)killCancelButton {
    for (NSUInteger itemIdx = 0; itemIdx < self.navigationBar.items.count; itemIdx++) {
        UINavigationItem *item = [self.navigationBar.items objectAtIndex:itemIdx];
        item.rightBarButtonItems = [[NSArray alloc] init];
    }
}