从 UIBarButtonItem 呈现时,如何防止在方向更改后重置 UIPopoverController passthroughViews? [英] How do I prevent UIPopoverController passthroughViews from being reset after orientation change when presented from a UIBarButtonItem?

查看:20
本文介绍了从 UIBarButtonItem 呈现时,如何防止在方向更改后重置 UIPopoverController passthroughViews?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个从 UIBarButtonItem 呈现的 UIPopoverController.我希望在弹出框之外进行触摸以消除弹出框.从条形按钮呈现弹出窗口时,其他条形按钮会自动包含在弹出窗口传递视图中.为了防止我在呈现弹出窗口后将直通视图设置为 nil(或 @[ ]),如下所示:

I have a UIPopoverController which is being presented from a UIBarButtonItem. I want touches outside of the popover to dismiss the popover. When presenting a popover from a bar button, the other bar buttons are automatically included in the popovers passthrough views. In order to prevent that I set the passthrough views to nil (or @[ ]) after presenting the popover, like so:

- (IBAction) consoleBarButtonHit:(id)sender {
UIViewController *consoleNavigationController=[self.storyboard instantiateViewControllerWithIdentifier:@"consoleNavigationController"];
_consolePopoverController=[[UIPopoverController alloc] initWithContentViewController:consoleNavigationController];
_consolePopoverController.delegate=self;

[_consolePopoverController presentPopoverFromBarButtonItem:sender permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];

// this must be done _after_ presenting the popover in order to work
_consolePopoverController.passthroughViews=nil;
}

这一切都很好,但是我遇到的问题是,在弹出窗口可见的情况下旋转设备后,栏按钮会自动重新添加为直通视图,并且不会导致弹出窗口被解雇.

如果我能以某种方式获得条形按钮视图(或矩形),那么我可以使用

If I could somehow get the bar buttons view (or rect) then I could present the popover using

-presentPopoverFromRect:inView:permittedArrowDirections:animated:

这可能会解决这个问题,但我不知道从 UIBarButtonItem 中找到该矩形/视图的任何非黑客方法.

which would likely fix this problem, but I don't know of any non-hackish way of finding that rect/view from a UIBarButtonItem.

我真的不希望在点击其他栏按钮时调用选择器以编程方式关闭弹出框,这不是他们的责任,以后可能会给我带来问题.

I really don't want the selectors called when the other bar buttons are hit to dismiss the popover programmatically, that's not their responsibility and will likely cause problems for me later.

有什么想法吗?

推荐答案

我采用的解决方案是不使用 passthroughViews 而是禁用/重新启用单个按钮 (UIBarButtonItem 实例)在工具栏或导航栏中,当 UIPopoverPresentationController 根据其转换呈现和关闭时.

The solution I went for was to leave passthroughViews alone and instead disable/re-enable individual buttons (UIBarButtonItem instances) in a toolbar or a navigation bar when UIPopoverPresentationController is presented and dismissed, based on its transition.

(iOS 8:UIPopoverPresentationController 而不是 UIPopoverController.)

(iOS 8: UIPopoverPresentationController instead of UIPopoverController.)

UIPopoverPresentationController+managedBarButtonItems.h

@interface UIPopoverPresentationController (managedBarButtonItems)

@property (nonatomic, retain) NSArray* managedBarButtonItems;

@end

UIPopoverPresentationController+managedBarButtonItems.m

#import "UIPopoverPresentationController+managedBarButtonItems.h"

#import <objc/runtime.h>

//
// scope: private, in-terms-of
//

@interface UIBarButtonItem (wasEnabled)

@property (nonatomic) BOOL wasEnabled;

@end

@implementation UIBarButtonItem (wasEnabled)

- (BOOL)wasEnabled
{
    return [objc_getAssociatedObject(self, @selector(wasEnabled)) boolValue];
}

- (void)setWasEnabled:(BOOL)wasIt
{
    objc_setAssociatedObject(self, @selector(wasEnabled), [NSNumber numberWithBool:wasIt], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

// FYI: "Associated objects are released [automatically] after the dealloc method of the original object has finished."

@end

//
// scope: consumable
//

@implementation UIPopoverPresentationController (managedBarButtonItems)

- (NSArray*)managedBarButtonItems
{
    return objc_getAssociatedObject(self, @selector(managedBarButtonItems));
}

- (void)setManagedBarButtonItems:(NSArray*)items
{
    objc_setAssociatedObject(self, @selector(managedBarButtonItems), items, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

// FYI: "Associated objects are released [automatically] after the dealloc method of the original object has finished."

- (void)presentationTransitionDidEnd:(BOOL)completed
{
    [super presentationTransitionDidEnd:completed];

    if (self.barButtonItem && self.managedBarButtonItems)
    {
        for (UIBarButtonItem* button in self.managedBarButtonItems)
        {
            if (button.action != /* actuator */ self.barButtonItem.action)
            {
                button.wasEnabled = button.enabled, button.enabled = NO;
            }
        }
    }
}

- (void)dismissalTransitionDidEnd:(BOOL)completed
{
    [super dismissalTransitionDidEnd:completed];

    if (self.barButtonItem && self.managedBarButtonItems)
    {
        for (UIBarButtonItem* button in self.managedBarButtonItems)
        {
            if (button.action != /* actuator */ self.barButtonItem.action)
            {
                button.enabled = button.wasEnabled;
            }
        }
    }
}

@end

用法:

UIAlertController* actionSheet = [UIAlertController
    alertControllerWithTitle:@"Actions" message:nil
        preferredStyle:UIAlertControllerStyleActionSheet];

UIPopoverPresentationController* presenter = actionSheet.popoverPresentationController;

// chosen anchor UIBarButtonItem
presenter.barButtonItem = anchorButton;

// disabled UIViewController buttons
presenter.managedBarButtonItems = self.toolbarItems;

也有可能:

// disabled UINavigationController buttons
presenter.managedBarButtonItems =
    [[NSArray arrayWithArray:self.navigationItem.leftBarButtonItems]
        arrayByAddingObject:self.navigationItem.rightBarButtonItem];

这篇关于从 UIBarButtonItem 呈现时,如何防止在方向更改后重置 UIPopoverController passthroughViews?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆