Есть ли способ различить, какой UIPopOver отклонен?

В моем приложении есть несколько всплывающих окон, и мне трудно определить, какое всплывающее окно было отклонено. Есть ли эквивалент функции «тег» для UIPopOvers?

Я могу NSLog popoverController в методе popoverContorllerDidDismissPopover и видеть ссылку на память каждого из них, но это не помогает.

#pragma mark - Popover controller delegates
- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController {
    NSLog(@"Popover dismised %@", popoverController);
}

person JasonBourne    schedule 19.03.2013    source источник
comment
Может быть, вы могли бы использовать UIPopOverController с блоками? Таким образом, вам не придется заботиться об этом.   -  person Rui Peres    schedule 19.03.2013
comment
Чего вы пытаетесь достичь?   -  person Mike D    schedule 19.03.2013
comment
Моя цель состоит в том, чтобы при закрытии определенного всплывающего окна я мог обновить пару разных состояний кнопок. Но только после того, как всплывающее окно будет закрыто. Да, я мог бы постоянно обновлять состояние кнопок в зависимости от того, что изменилось, но это не мое требование.   -  person JasonBourne    schedule 19.03.2013
comment
Я думаю, что в этом случае вы, возможно, захотите изучить использование делегата.   -  person Mike D    schedule 19.03.2013


Ответы (3)


Выдержка из здесь:

Если я понимаю вопрос, то в принципе нет - и это сводит с ума. С одной стороны, вам говорят, что в любой момент должно отображаться только одно всплывающее окно. С другой стороны, вы не получаете автоматически ссылку на это всплывающее окно. Таким образом, вы должны вручную сохранить ссылку на текущий контроллер всплывающего окна в то время, когда он показывает свое всплывающее окно, чтобы вы могли поговорить с ним позже, чтобы отклонить его. Таким образом, управление всплывающим контроллером может стать очень сложным и неуклюжим; вы делаете всю работу, которую система должна делать за вас.

iOS в этом плане забавна. Мне напомнили, что в iOS 4 нет звонка, который сообщает вам о текущем первом ответчике. Очевидно, что система знает, что такое первый респондент, так почему же она не скажет вам? Это глупо. Это похоже; система явно знает полезные вещи, которыми она не поделится с вами. м.

person Anoop Vaidya    schedule 19.03.2013
comment
В соответствии с HIG должно отображаться только одно всплывающее окно... остальное, как вы уже догадались. - person Anoop Vaidya; 19.03.2013
comment
Я действительно не понимаю проблемы с сохранением ссылки на представленное всплывающее окно. Для каждого всплывающего окна вы просто сохраняете ссылку и проверяете ссылку в DidDismiss. Я пропустил что-то еще из вопроса? - person John; 19.03.2013
comment
@Джон Ты абсолютно прав. Однако введение новой переменной состояния не всегда является лучшим решением. В сложном приложении для iPad у вас может быть много разных всплывающих окон, отображаемых на одном экране, и если вы обработаете их все одним методом делегата, вы получите большое switch или if-else для сравнения типа всплывающего окна. Лучше удалить switch и переместить обработчик отклонения ближе к коду, создающему всплывающее окно, например. используя блоки (проверьте мой ответ). - person Sulthan; 19.03.2013

Есть много способов отличить всплывающие окна. Я перечислю некоторые из них:

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

  2. Сохраните тип всплывающего окна в переменной/свойстве в вашем контроллере, например. как enum. Это самый простой способ.

  3. Добавьте необходимую информацию во всплывающее окно, но будьте умны, например.

@interface MyPopoverController : UIPopoverController 

@property (nonatomic, copy, readwrite) void (^dissmissHandler)(void);

@end

@implementation MyPopoverController 

- (id)initWithContentViewController:(UIViewController*)contentView {
   self = [super initWithContentViewController:contentView];

   if (!self) {
      return nil;
   }

   self.delegate = self;

   return self;
}

- (void)popoverControllerDidDismissPopover:(UIPopoverController*)popover {
    assert(popover == self);

    if (self.dissmissHandler) {
       self.dissmissHandler();
    }
}

@end

MyPopoverController* popover = [MyPopoverController alloc] initWithContentViewController:...];
popover.dissmissHandler = ^{
   ...
};

person Sulthan    schedule 19.03.2013
comment
(добавьте autorelease и dealloc для MRC) - person Sulthan; 19.03.2013
comment
Блоки для меня все еще очень абстрактное понятие. - person JasonBourne; 19.03.2013
comment
@JasonBourne Хорошо, но рано или поздно тебе придется их понять. Это не единственный вариант, который я перечислил. - person Sulthan; 19.03.2013

Как заявил @Anoop, обычно вы можете отображать только одно всплывающее окно за раз.

Одним из возможных решений является проверка свойства contentViewController во всплывающем окне. Если вы сохраняете ссылку на каждый контроллер представления, вы можете сделать что-то вроде:

- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController {
    if ( popoverController.contentViewController == self.someUIViewController ) {
        // do stuff
    }
    else if ( popoverController.contentViewController == someoTherViewController ) {
       //
    }
    NSLog(@"Popover dismised %@", popoverController);
}

Если сохранение ссылки на каждый контроллер представления контента невозможно (или, может быть, просто не очень хорошая идея), вы всегда можете проверить его тип:

- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController {
    if ( [popoverController.contentViewController isKindOfClass:[MyAwesomeViewController class]] ) {
        // do stuff
    }
    else if ( [popoverController.contentViewController isKindOfClass:[MyOtherViewController class]] ) {
        //
    }
    NSLog(@"Popover dismised %@", popoverController);
}

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

person Mike D    schedule 19.03.2013