16

在 iPad 上,可以使用 -showFromBarButtonItem:animated: 显示 UIActionSheet。这很方便,因为它在操作表周围包裹了一个 UIPopoverController,并将弹出框的箭头指向传入的 UIBarButtonItem。

但是,此调用将 UIBarButtomItem 的工具栏添加到直通视图列表中 - 这并不总是可取的。而且,如果没有指向 UIPopoverController 的指针,就无法将其他视图添加到直通列表中。

有谁知道获得指向弹出控制器的指针的认可方法?

提前致谢。

4

7 回答 7

10

您需要根据方向变化进行调整。

我找到了一个替代解决方案,它对我来说非常有效。

依照

- (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
}

并且不要忘记在

- (void)dealloc

我相信这会奏效。

于 2010-05-12T11:23:03.767 回答
9
    if ([[[[actionSheet superview] superview] nextResponder] respondsToSelector:@selector(setPassthroughViews:)]) {
        [[[[actionSheet superview] superview] nextResponder] performSelector:@selector(setPassthroughViews:) withObject:nil];
    }

会成功的,这不应该对 App Reviewers 造成任何问题,因为它不调用任何私有 API。

它很脆弱 - if 语句确保您的代码在 Apple 更改底层实现的不太可能的情况下不会崩溃(只是不起作用)。

于 2011-05-04T11:40:17.190 回答
4

我怀疑是否有一种认可的方法,因为操作表出现在 UIPopoverViews 中,它链接到 UIViewController 而不是 UIPopoverController

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

查看 UIPopoverView 头文件 (UNDOCUMENTED) 会产生以下解决方案,尽管没有记录。怀疑您是否可以通过 App Reviewers 偷偷摸摸,但如果您认为值得一试,请试一试。

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];
于 2010-05-13T09:29:35.293 回答
2

我不认为这是可行的。我坐着也有同样的问题。

利用

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

例子:

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

注意:您必须更改 objectAtIndex: 的索引以适合您的情况并参考您的 ToolBar

于 2010-05-11T14:45:18.590 回答
2

这是解决方案。我刚刚发现它,这很容易。在显示操作表之前将 userInteractionEnabled 设置为 NO,并在您的操作表委托方法结束时将其设置为 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;
}
于 2013-04-15T04:39:37.103 回答
2

几年来我一直在使用 nbransby 的答案,但这在 iOS 8 中不再适用。但是,iOS 8 中的新问题仍然存在UIAlertController。这是一个适合我的更新:

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,但您可以方便地使用完成块来执行此操作。

于 2014-12-23T18:20:42.813 回答
1

从栏按钮项目呈现时,您通常希望禁用工具栏上的所有其他按钮,直到关闭操作表。

我认为最简单的方法是修改 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

然后只需在您之前使用 UIToolbar 的代码中使用 UIToolbarWithModal 即可。

于 2010-11-05T17:29:49.287 回答