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
}

で popoverActionsheet をリリースすることを忘れないでください

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

トリックを実行します。プライベート API を呼び出していないため、アプリ レビュー担当者に問題が発生することはありません。

それは脆弱です - if ステートメントは、万一 Apple が基礎となる実装を変更した場合でも、コードがクラッシュしない (単に機能しない) ことを保証します。

于 2011-05-04T11:40:17.190 に答える
4

アクションシートは UIPopoverController ではなく UIViewController にリンクされている UIPopoverViews に表示されるため、これに対する認可されたアプローチがあるとは思えません

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

UIPopoverView ヘッダー ファイル (UNDOCUMENTED) を調べると、文書化されていませんが、次の解決策が得られます。アプリのレビュアーを無視できるかどうかは疑問ですが、試してみる価値があると思われる場合は試してみてください.

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: のインデックスを状況に合わせて変更し、ツールバーを参照する必要があります。

于 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

私は数年間 nbrasby の回答を使用してきましたが、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 に答える