UIStoryboardPopoverSegue открытие нескольких окон при нажатии кнопки - PullRequest
15 голосов
/ 13 октября 2011

Я использую UIStoryboardPopoverSegue для представления всплывающего окна для приложения iOS 5 для iPad.Segue прекрасно работает, но кажется, что панель инструментов, которая содержит кнопку, является сквозным видом для контроллера поповер, поэтому если вы продолжите нажимать кнопку, появится больше всплывающих окон.Поскольку я сам не создаю и не отслеживаю UIPopoverController (как это делает раскадровка), я не могу отклонить его, когда снова нажмем кнопку.Кто-нибудь еще сталкивался с этим?У меня есть ошибка, открытая в Apple, но они не ответили.

РЕДАКТИРОВАТЬ : я решил это, используя ответ ниже.Вот код, который я использовал в конечном итоге.currentPopover - это __weak ivar в моем классе контроллера представления, поэтому, когда контроллер завершит работу, он автоматически упадет до нуля.

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
    if([segue isKindOfClass:[UIStoryboardPopoverSegue class]]){
        // Dismiss current popover, set new popover
        [currentPopover dismissPopoverAnimated:YES];
        currentPopover = [(UIStoryboardPopoverSegue *)segue popoverController];
    }
}

Ответы [ 7 ]

7 голосов
/ 10 ноября 2011

Есть некоторые визуальные проблемы с вашим решением Кори.

Два варианта, которые можно рассмотреть - просто удалите или измените действие кнопки, которая представляет всплывающее окно.

Вариант 1, удерживайте указатель на действие кнопки, и после того, как появится всплывающее окно, установите для действия значение nil. После увольнения всплывающего окна восстановить исходное действие.

-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{

    action = [sender action];
    [sender setAction:nil];

    self.currentPopover = [(UIStoryboardPopoverSegue *)segue popoverController];
    self.currentPopover.delegate = self;
}

-(BOOL)popoverControllerShouldDismissPopover:(UIPopoverController *)popoverController
{
    [self.navigationItem.rightBarButtonItem setAction:action];

    return YES;
}

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

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

    -(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
    {

        action = [sender action];
        target = [sender target];

        [sender setTarget:self];
        [sender setAction:@selector(dismiss:)];

        self.currentPopover = [(UIStoryboardPopoverSegue *)segue popoverController];
        self.currentPopover.delegate = self;
    }

-(void)dismiss:(id)sender
{
    [self.navigationItem.rightBarButtonItem setAction:action];
    [self.navigationItem.rightBarButtonItem setTarget:target];
    ////or
//  [sender setAction:action];
//  [sender setTarget:target];
    [self.currentPopover dismissPopoverAnimated:YES];
}


    -(BOOL)popoverControllerShouldDismissPopover:(UIPopoverController *)popoverController
    {
        [self.navigationItem.rightBarButtonItem setAction:action];
        [self.navigationItem.rightBarButtonItem setTarget:target];

        return YES;
    }
3 голосов
/ 15 февраля 2012

Просто подключите UIBarButtonItem через IBAction. Используйте набор указателей в конструкторе интерфейса:

-(IBAction)barButtonItemPressed:(id)sender {
    if (currentPopoverController && currentPopoverController.popoverVisible) {
        [currentPopoverController dismissPopoverAnimated:YES];
        currentPopoverController = nil;
    } else {
        [self performSegueWithIdentifier:@"aSegueIdentifier" sender:sender];
    }
}

Получить ссылку на новый UIPopoverCOntroller из последовательности:

-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    if ([[segue identifier] isEqualToString:@"aSegueIdentifier"])
        currentPopoverController = [(UIStoryboardPopoverSegue *)segue popoverController];
}

currentPopoverController - переменная экземпляра, определенная в заголовочном файле:

UIPopoverController *currentPopoverController;

Важное замечание: Свойство привязки seque должно быть установлено на соответствующий UIBarButtonItem!

2 голосов
/ 28 августа 2012

Я предпочитаю использовать статическую слабую переменную, которая хранит все вместе в одном месте:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender  
{
    if ([[segue identifier] isEqualToString:@"showSomething"]) {
        static __weak UIPopoverController* currentPopover = nil;
        [currentPopover dismissPopoverAnimated:NO];
        currentPopover = [(UIStoryboardPopoverSegue *)segue popoverController];
        // ...
    }
}

Нет причин добавлять отдельную дополнительную переменную (когда у вас будет несколько экземпляров контроллера представления?), И таким образом вы можете добавить дополнительную переменную для каждого блока if ().

2 голосов
/ 13 февраля 2012

У этого решения также могут быть визуальные проблемы, но это не так для моего простого случая.В моем случае поповер просто отображал некоторую помощь.Я соединил следующее (с ARC), которое будет отклонять контроллеры представления popover при повторном нажатии кнопки панели кнопок (как оригинальной, так и вновь созданной).

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{   
    if( [segue isKindOfClass:[UIStoryboardPopoverSegue class]] )
    {
        UIStoryboardPopoverSegue *popoverSegue      = (id)segue;
        UIPopoverController      *popoverController = popoverSegue.popoverController;

        if( m_popoverController.popoverVisible )
        {
            [m_popoverController dismissPopoverAnimated:NO];
            dispatch_async( dispatch_get_main_queue(), ^{
                [popoverController dismissPopoverAnimated:YES];
            });
            m_popoverController = nil;
        }
        else
            m_popoverController = popoverController;        
    }    
}

Я также добавил некоторую очисткув dealloc

- (void)dealloc
{
    if( m_popoverController.popoverVisible )
        [m_popoverController dismissPopoverAnimated:YES];
}

Требуется переменная-член в вашем классе

UIPopoverController *m_popoverController;
2 голосов
/ 16 октября 2011

Вы должны сохранить ссылку на свойство popoverController, переданное как часть класса UIStoryboardPopoverSegue в методе класса prepareForSegue.

Чтобы получить к нему доступ, перезапустите метод в вызывающем контроллере представления следующим образом:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    // The Storyboard Segue is named popover in this case:
    if ([segue.identifier compare:@"popover"] == NSOrderedSame) {
        // segue.popoverController is only present in popover segue's
        // self.seguePopoverController is a UIPopoverController * property.
        self.seguePopoverController = segue.popoverController;
    }
}

Затем вы можете отклонить его обычным способом.

1 голос
/ 14 июня 2013

14 июня 2013

Спасибо за редактирование.Вместо того, чтобы игнорировать и воссоздавать контроллер представления - чтобы избежать проблем производительности и батареи и предотвратить Flash при отключении и воссоздании контроллера представления - как насчет предотвращения появления второго экземпляра popover?

//place in view controller (tested iOS6+, iPad, iPhone)
__weak UIPopoverController *popover;
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    if([segue isKindOfClass:[UIStoryboardPopoverSegue class]] 
        && [segue.identifier isEqualToString:@"mySegue"]) //remember to change "mySegue" 
            popover = [(UIStoryboardPopoverSegue *)segue popoverController];
}
- (BOOL)shouldPerformSegueWithIdentifier:(NSString *)identifier sender:(id)sender {
    if ([identifier isEqualToString:@"mySegue"]) //remember to change "mySegue"
        return !popover;
    else
        return YES;
}
added checks to: http://stackoverflow.com/a/10238581/1705353 
0 голосов
/ 08 ноября 2011

Это тоже хорошо.

@interface ViewController : UIViewController <UIPopoverControllerDelegate> {
    UIPopoverController * seguePopoverController;
}

@property (strong) UIPopoverController * seguePopoverController;

@end

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender  
{
    if (self.seguePopoverController) {
        [self.seguePopoverController dismissPopoverAnimated:NO];
        self.seguePopoverController = nil;
    }

    // The Storyboard Segue is named popover in this case:
    if ([[segue identifier] isEqualToString:@"popover"]) {

        UIStoryboardPopoverSegue* popSegue = (UIStoryboardPopoverSegue*)segue;
        UIPopoverController *thePopoverController = [popSegue popoverController];
        thePopoverController.delegate = self;
        self.seguePopoverController = thePopoverController;

    }
}

- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController
{
    self.seguePopoverController = nil;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...