Подтвердить что ты не робот

Доступ к UIPopoverController для UIActionSheet на iPad

На iPad можно показать таблицу UIActionSheet, используя -showFromBarButtonItem: animated:. Это удобно, потому что он обертывает UIPopoverController вокруг листа действий и указывает стрелку popover на UIBarButtonItem, который передан.

Тем не менее, этот вызов добавляет панель инструментов UIBarButtomItem в список представлений пересылки - что не всегда желательно. И, не указав на UIPopoverController, нельзя добавить другие представления в список переходов.

Кто-нибудь знает о санкционированном подходе к указанию на контроллер popover?

Спасибо заранее.

4b9b3361

Ответ 1

Вам нужно будет отрегулировать изменение ориентации.

Я нашел альтернативное решение, которое отлично работает для меня.

Придерживайтесь

- (void)showFromBarButtonItem:(UIBarButtonItem *)item animated:(BOOL)animated

В вашем @interface добавьте

UIActionSheet *popoverActionsheet;

также добавить

@property (nonatomic, retain) UIActionSheet *popoverActionsheet;

также добавить

- (IBAction)barButtonItemAction:(id)sender;

Таким образом, вы ссылаетесь на свою таблицу действий из любой точки вашей реализации.

в вашей реализации

- (IBAction) barButtonItemAction:(id)sender
{
    //If the actionsheet is visible it is dismissed, if it not visible a new one is created.
    if ([popoverActionsheet isVisible]) {
        [popoverActionsheet dismissWithClickedButtonIndex:[popoverActionsheet cancelButtonIndex] 
                                                     animated:YES];
        return;
    }

    popoverActionsheet = [[UIActionSheet alloc] initWithTitle:nil
                                                     delegate:self
                                            cancelButtonTitle:nil 
                                       destructiveButtonTitle:nil
                         otherButtonTitles:@"Save Page", @"View in Safari", nil];

    [popoverActionsheet showFromBarButtonItem:sender animated:YES];
}

в вашем дележе делегата.

- (void)actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex
{

    if (buttonIndex == [actionSheet cancelButtonIndex]) return;

    //add rest of the code for other button indeces
}

и не забудьте выпустить popoverActionsheet в

- (void)dealloc

Я верю, что это будет сделано.

Ответ 2

    if ([[[[actionSheet superview] superview] nextResponder] respondsToSelector:@selector(setPassthroughViews:)]) {
        [[[[actionSheet superview] superview] nextResponder] performSelector:@selector(setPassthroughViews:) withObject:nil];
    }

Сделаем трюк, это не должно вызывать никаких проблем с Рецензентами приложений, поскольку он не вызывает каких-либо частных API.

Он хрупкий - операторы if гарантируют, что ваш код не будет сбой (просто не работает) в маловероятном случае Apple изменит базовую реализацию.

Ответ 3

Я сомневаюсь, что существует санкционированный подход к этому, поскольку таблицы действий представлены в UIPopoverViews, который связан с UIViewController, а не с UIPopoverController

NSLog(@"%@",[[[popoverActionsheet superview] superview] passthroughViews]);

Просматривая заголовочный файл UIPopoverView (UNDOCUMENTED), выдается следующее решение, хотя и недокументированное. Сомневайтесь, что вы можете хихикать, что мимо Рецензентов App, но отпустите его, если вы считаете, что это стоит того.

http://github.com/kennytm/iphone-private-frameworks/blob/master/UIKit/UIPopoverView.h

NSArray *passthroughViews = [[[popoverActionsheet superview] superview] passthroughViews];

        NSMutableArray *views = [passthroughViews mutableCopy];
        [views addObject:[self view]];
        [[[popoverActionsheet superview] superview] setPassthroughViews:views];
        [views release];

Ответ 4

Я не думаю, что это возможно. Я сидел с той же проблемой.

Используйте

- (void)showFromRect:(CGRect)rect inView:(UIView *)view animated:(BOOL)animated

Пример:

[actionSheet showFromRect:[[[myToolBar subviews] objectAtIndex:0] frame] inView:myToolBar animated:YES];

Примечание. Вы должны изменить индекс для объектаAtIndex: чтобы соответствовать вашей ситуации и иметь ссылку на ваш ToolBar

Ответ 5

Вот решение. Я только что открыл его, и это так просто. Установите userInteractionEnabled в НЕТ, прежде чем показывать лист действий и установите для него значение YES в конце метода делегирования листа действия для отклонения.

- (void)promptResetDefaults:(id)sender
{
    UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:nil
                                                             delegate:self
                                                    cancelButtonTitle:nil
                                               destructiveButtonTitle:NSLocalizedString(@"Reset All Defaults", nil)
                                                    otherButtonTitles:nil];

    self.navigationController.navigationBar.userInteractionEnabled = NO;
    [actionSheet showFromBarButtonItem:sender animated:YES];
}

- (void)actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex
{
    if (buttonIndex == actionSheet.destructiveButtonIndex)
    {
        [self.dataDefaults resetDataDefaults];
        [self.tableView reloadData];
    }

    self.navigationController.navigationBar.userInteractionEnabled = YES;
}

Ответ 6

Я использую ответ nbransby на пару лет, но это больше не работает в iOS 8. Однако проблема все еще существует с новым UIAlertController в iOS 8. Здесь обновление, которое работает для меня:

UIAlertController *actionSheet = [UIAlertController
    alertControllerWithTitle:@"Test"
    message:@"Hello, world!"
    preferredStyle:UIAlertControllerStyleActionSheet];
[actionSheet addAction:[UIAlertAction
    actionWithTitle:@"OK"
    style:UIAlertActionStyleDefault
    handler:^(UIAlertAction *action) {}]];
actionSheet.modalPresentationStyle = UIModalPresentationPopover;
actionSheet.popoverPresentationController.barButtonItem = testButton;
[self presentViewController:actionSheet animated:TRUE completion:^(void) {
    actionSheet.popoverPresentationController.passthroughViews = [NSArray array];
}];

Обратите внимание, что passthroughViews должен быть установлен после появления popover, но вы можете удобно использовать блок завершения для этого.

Ответ 7

При представлении из элемента кнопки панели вы обычно хотите отключить все остальные кнопки на панели инструментов, пока лист действий не будет отклонен.

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

Сделайте файл UIToolbar + Modal.m, например:

@implementation UIToolbar (Modal)

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
  UIView *hitView = [super hitTest:point withEvent:event];

  UIActionSheet *mySheet = [[[UIApplication sharedApplication] delegate] myActionSheet];
  if ([mySheet isVisible]) return nil;
  else return hitView;
}

@end

Файл .h не должен содержать ничего особенного

@interface UIToolbar (Modal) {
}
@end

Кстати, прежде чем найти это решение, я попытался назначить пустой массив для passthroughViews, к которому вы можете получить доступ (первоначально), описанный stalinkay, но на самом деле это не работает (в дополнение к недокументированности).

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

ОБНОВЛЕНИЕ

Начиная с iOS 4.3 это больше не работает. Вы должны подклассы:

UIToolbarWithModal.h

#import <Foundation/Foundation.h>

@interface UIToolbarWithModal : UIToolbar {
}

@end

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

UIToolbarWithModal.m

#import "UIToolbarWithModal.h"
#import "MyDelegate.h"

@implementation UIToolbarWithModal

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
  UIView *hitView = [super hitTest:point withEvent:event];

  UIActionSheet *mySheet = [[[UIApplication sharedApplication] delegate] myActionSheet];
  if ([mySheet isVisible]) return nil;
  else return hitView;
}

@end

Затем просто используйте UIToolbarWithModal в своем коде, где раньше вы использовали UIToolbar.