Закрытие iPad UIPopoverController, когда BarButtonItem нажимается, когда он открыт

Используя разделенный вид на iPad, у меня есть следующий код:

- (void) splitViewController:(UISplitViewController *)svc willHideViewController:(UIViewController *)aViewController withBarButtonItem:(UIBarButtonItem *)barButtonItem forPopoverController:(UIPopoverController *)pc {
  barButtonItem.title = @"Categories";
  NSMutableArray *items = [[toolbar items] mutableCopy];
  [items insertObject:barButtonItem atIndex:0];
  [toolbar setItems:items animated:YES];
  [items release];
  self.popoverController = pc;
}

Это хорошо работает, чтобы показать всплывающее окно при нажатии кнопки. Тем не менее, я также хотел бы, чтобы всплывающее окно закрывалось, если кнопка нажата, когда она уже открыта, чтобы следовать хорошим рекомендациям. Как мне это сделать? (т. е. если пользователь неоднократно нажимает эту кнопку, всплывающее окно должно появляться и скрывать каждое второе нажатие.)


person joshholat    schedule 15.04.2010    source источник


Ответы (7)


При отображении всплывающего окна splitViewController будет вызываться метод ниже. Просто проверьте, если не ноль, то отклоните его :)

- (void)splitViewController:(UISplitViewController*)svc popoverController:(UIPopoverController*)pc willPresentViewController:(UIViewController *)aViewController{
  if ([pc isPopoverVisible]) {
     [pc dismissPopoverAnimated:YES];
  }
}
person sunnycmf    schedule 08.06.2010
comment
Это единственный ответ здесь, который фактически решает исходный вопрос, который был специально связан с всплывающими окнами и элементами панели инструментов, созданными UISplitViewControllers. Решил это для меня, спасибо. - person Chris Miles; 13.07.2010
comment
Вы должны использовать свойство всплывающего окна isPopoverVisible для проверки вместо проверки, если nil - person PostCodeism; 10.12.2010
comment
@OOP_Master спасибо за исправление, я соответственно обновил образец: D - person sunnycmf; 03.01.2012

HIG от Apple говорит, что во всплывающем окне не должно быть явной кнопки закрытия, но чтобы сделать то, что вы просите, у вас есть два варианта.

1) опубликовать NSNotification

OR

2) углубляйтесь в иерархию представлений, пока у вас не появится экземпляр всплывающего окна

1) в зависимости от того, в каком представлении вы представляете всплывающее окно, в методе viewDidLoad:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(dismissThePopover) name:@"popoverShouldDismiss" object:nil];

создайте метод с именем dismissThePopover и в методе Dealloc удалите Observer

-(void)dismissThePopover {
    [self.popoverController dismissPopoverAnimated:YES];
}

-(void)dealloc {
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

В кнопке «отклонить» popoverController введите следующую строку:

[[NSNotificationCenter defaultCenter] postNotificationName:@"popoverShouldDismiss" object:nil];

Это отправляет уведомление в приложение, и, поскольку вы зарегистрировали свой другой контроллер представления для его прослушивания, всякий раз, когда он видит это уведомление, он вызывает указанный вами селектор, в данном случае, rejectThePopover.

2) углубитесь в иерархию представлений, чтобы найти self.popoverController

проверьте это, у вас, конечно, будет по-другому, но общая идея та же. Начните с вашего AppDelegate, перейдите в первый контроллер представления, перейдите в подпредставления, пока не дойдете до своего объекта self.popoverController.

MyAppDelegate *appDelegate = [[UIApplication sharedApplication]delegate];
//appDelegate instance, in this case it's the .m file for your ApplicationDelegate

UISplitViewController *svc = appDelegate.splitViewController;
//In this case the first view inside the appDelegate is a SplitView, svc

UINavigationController *navc = [[svc viewControllers]objectAtIndex:0];
//a navigationController is at index:0 in the SplitView hierarchy. DetailView is at index:1

NSArray *vcs = [navc viewControllers];
//vcs is the array of different viewcontrollers inside the Navigation stack for nvc

iPadRootViewController *rootView = [vcs objectAtIndex:0];
//declare the rootView, which is the .m file that is at index:0 of the view array

UIPopoverController *pc = [rootView popoverController];
//HERE WE GO!!! popoverController is a property of iPadRootViewController's instance rootView, hereby referred to as pc.

[pc dismissPopoverAnimated:YES];
//bye bye, popoverController!

Надеюсь это поможет

person Justin    schedule 22.04.2010
comment
Спасибо, я уже пользовался уведомлениями и обязательно попробую этот метод еще раз. - person joshholat; 29.04.2010

Это намного проще, потому что popoverController является свойством. Облегчает ссылку.

if ([self.popoverController isPopoverVisible]) {
    //using the setters and getters "goes thru the proper channels" when accessing objects
    [self.popoverController dismissPopoverAnimated:YES];
} else {
    UIPopoverController *pc = [[UIPopoverController alloc] initWithContentViewController:YOUR_VIEW_CONTROLLER];
    self.popoverController = pc;
    [pc release];

    //get the button instance you set on the toolbar
    UIBarButtonItem *categoryButton = [[toolbar items] objectAtIndex:0];
    [self.popoverController presentPopoverFromBarButtonItem:categoryButton permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}

На самом деле я только что понял, что вы имеете в виду код внутри метода Delegate для отображения viewController по индексу: 0 вашего splitView. Этот ответ не обязательно относится к этому, но применим к любому другому времени, когда вы получаете доступ и создаете popoverControllers на iPad. Не проверив сначала, отображается ли всплывающее окно, вы либо выйдете из строя, либо откроете несколько всплывающих окон.

Спасибо за ваше время.

person Justin    schedule 21.04.2010
comment
Я пытаюсь создать всплывающее окно на своем iPad не с панели инструментов, а затем закрыть его с помощью кнопки на нем. Я только сейчас понял, что код, который я вставил, неверен. - person joshholat; 21.04.2010

Вы можете попробовать ниже

if(![popoverController isPopoverVisible]){
   // Show popover
}
else{
   // close popover
   [popoverController dismissPopoverAnimated:YES];
}
person Podcaster123    schedule 17.04.2010

Если вы используете настройку UISplitViewController по умолчанию, то созданная кнопка панели навигации отображает всплывающее окно вашего RootViewController.

Если вы хотите, чтобы у вас не было одновременно нескольких всплывающих окон, вы можете просто отклонять всплывающие окна всякий раз, когда появляется ваш RootViewController. Вот код, который я использовал для решения этой проблемы:

- (void) viewWillAppear:(BOOL)animated {
  if ([self.popover isPopOverVisible]) {
    [self.popover dismissPopoverAnimated:YES];
  }
  [super viewWillAppear:YES];
}
person Smorpheus    schedule 28.05.2010

Код, который я использовал для отображения всплывающего окна в RootViewController.m:

- (IBAction) addCategory:(id)sender {
  AddCategoryViewController *content = [[AddCategoryViewController alloc] init];
  UIPopoverController *aPopover = [[UIPopoverController alloc]
                                   initWithContentViewController:content];

  aPopover.delegate = self;

  // Store the popover in a custom property for later use.
  self.addCategoryPopover = aPopover;
  addCategoryPopover.delegate = self;
  [aPopover release];
  [content release];

  [addCategoryPopover presentPopoverFromBarButtonItem:sender permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
}

Это я использовал, чтобы попытаться отклонить его из другого класса:

-(IBAction)saveAddCategory:(id)sender {
  rootViewController = [[RootViewController alloc] init];
  [rootViewController dismissPopover];
}

Моя функция dismissPopover выглядит так:

- (void) dismissPopover {
  if ([self.addCategoryPopover isPopoverVisible]) {
    [self.addCategoryPopover dismissPopoverAnimated:YES];
  }
  if (addCategoryPopover.popoverVisible == YES) {
    [addCategoryPopover dismissPopoverAnimated:YES];
  }
}
person joshholat    schedule 21.04.2010

Да, вы можете установить modalPresentationStyle следующим образом:

controller.modalPresentationStyle = UIModalPresentationFormSheet;
person Son Nguyen    schedule 28.12.2010