从 UIBarButtonItem 呈现时,如何防止在方向更改后重置 UIPopoverController passthroughViews? [英] How do I prevent UIPopoverController passthroughViews from being reset after orientation change when presented from a UIBarButtonItem?
问题描述
我有一个从 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屋!