ipad - 关闭 UIPopoverController
Posted
技术标签:
【中文标题】ipad - 关闭 UIPopoverController【英文标题】:ipad - dismissing a UIPopoverController 【发布时间】:2010-04-13 14:25:53 【问题描述】:我在 UIPopoverController 的内容中有一个按钮。此按钮运行一个名为 myAction 的方法。
MyAction 的形式为
- (void) myAction:(id)sender
所以,myAction 接收到调用者按钮的 id。
现在,在这个方法中,我想关闭 UIPopoverController,但我唯一拥有的是调用者按钮的 ID。请记住,按钮位于 UIPopoverController 内。
根据我已有的按钮 ID,有没有办法发现 UIPopoverController 的 ID?
谢谢。
【问题讨论】:
【参考方案1】:很遗憾,没有。至少,不在标准实践范围内。您也许可以沿着响应程序堆栈向上移动以找到它,但它是一个 hack,它有问题,而且非常非常混乱。
如果您想通过按下按钮来关闭弹出框,则某些相关位置应保留对弹出框的引用。通常这将是弹出框的所有者(不是控制器显示在弹出框)。当按钮被按下时,它可以向所有者控制器发送一条消息,然后它可以关闭弹出框。
您可能想让显示在弹出框内的控制器成为其自己的弹出框的所有者,但这种方式编码很脆弱,可能会(再次)变得混乱,并且可能导致保留循环,因此两者都不会被释放.
【讨论】:
第二段在这个答案中非常重要。请记住,根据 iPad 编程指南:“但请注意,存储对弹出框控制器的引用是您的责任,以便您可以关闭它。系统默认不提供。”因此,在父视图进入 dealloc 阶段之前,不要对其执行“释放]”(无论如何都会导致崩溃)。 (这是我的安全方法)。 只需使用 [self dismissViewControllerAnimated:YES completion:nil]; “呈现视图控制器负责关闭它呈现的视图控制器。如果你在呈现视图控制器本身上调用此方法,它会自动将消息转发到呈现视图控制器。”【参考方案2】:您可以通过使用 KVC 访问“popoverController”来访问呈现的 popoverController。
[[self valueForKey:@"popoverController"] dismissPopoverAnimated:YES]
【讨论】:
聪明,但是这是否有可能被标记为“使用私有 API”并且应用程序被拒绝,即使从技术上讲它没有使用私有 API? 是的@Chintan。如果 AppStore 检测到您的代码正在使用他们的“私有 API”,它可能会被拒绝。 @JasonMing 这是唯一对我有用的东西,我花了 5 个小时的大部分时间来寻找解决方案。非常感谢... 他们的“私有 API”是什么意思?谁能解释一下? 只是出于兴趣,如果可以使用KVC,为什么不能写self.popoverController?【参考方案3】:我有这个工作,我不认为这是一个黑客。我有一个标准的拆分视图 iPad 应用程序。然后我在我的细节控制器(弹出窗口的所有者)上添加了一个方法来处理解雇。
在标准的拆分视图架构中,根视图控制器和详细视图控制器都可以通过应用程序委托获得。因此,我在弹出窗口中绑定了一个按钮单击以调用获取应用程序委托的方法。从那里我调用细节控制器上的方法来关闭弹出窗口。
这是弹出框内显示的视图控制器上的方法的代码:
- (void) exitView: (id)sender
MyAppDelegate *appDelegate = (MyAppDelegate *)[[UIApplication sharedApplication] delegate];
[appDelegate.detailViewController exitDrill];
然后在详细视图控制器上关闭的简单方法:
- (void) exitDrill
if(dtController != nil)
[dtController dismissPopoverAnimated: YES];
[dtController release];
我喜欢这样做的能力,因为它让我可以向用户展示如何退出弹出窗口。在应用程序的未来版本中可能不需要这样做;目前,虽然这个范例对于平台来说还是新的,但我更喜欢让用户以几种不同的方式退出显示器,以确保我最大限度地减少挫败感。
【讨论】:
【参考方案4】:正如 Ed Marty 已经写的那样
如果你想通过按下按钮来关闭弹出框,一些相关的地方应该保留对弹出框的引用
这是非常正确的;但是,当显示 UIPopoverController 时,打开 popovercontroller 的类已经保留了该资源。所以,你可以做的是使用这个类作为你的 Popover 控制器的委托类。
为此,您可以执行以下操作,我在代码中使用了这些操作。 在打开弹出框的类中,这是我的代码:
- (void)showInformationForView:(Booking*)booking frame:(CGRect)rect
BookingDetailsViewController *bookingView = [[BookingDetailsViewController alloc] initWithStyle:UITableViewStyleGrouped booking:booking];
[bookingView setDelegate:self];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:bookingView];
self.popController = [[UIPopoverController alloc] initWithContentViewController:navController];
[self.popController setDelegate:self];
[self.popController setPopoverContentSize:CGSizeMake(320, 320)];
rect.size.width = 0;
[self.popController presentPopoverFromRect:rect inView:self.view permittedArrowDirections:UIPopoverArrowDirectionLeft animated:YES];
- (void)dismissPopoverAnimated:(BOOL)animated
[self.popController dismissPopoverAnimated:animated];
所以我在这里做的是创建一个UINavigationController
并将BookingDetailsViewController
设置为其rootViewController
。然后我还将当前类作为委托添加到这个BookingDetailsViewController
。
我添加的第二件事是一个名为dismissPopoverAnimated:animated
的解除方法。
在我的BookingDetailsViewController.h
中,我添加了以下代码:
[...]
@property (nonatomic, strong) id delegate;
[...]
在我的BookingDetailsViewController.m
中,我添加了以下代码:
[...]
@synthesize delegate = _delegate;
- (void)viewDidLoad
UIBarButtonItem *closeButton = [[UIBarButtonItem alloc] initWithTitle:@"Close" style:UIBarButtonItemStylePlain target:self action:@selector(closeView)];
[self.navigationItem setRightBarButtonItem:closeButton];
[super viewDidLoad];
- (void)closeView
if ([self.delegate respondsToSelector:@selector(dismissPopoverAnimated:)])
[self.delegate dismissPopoverAnimated:YES];
else
NSLog(@"Cannot close the view, nu such dismiss method");
[...]
当按下 UINavigationController 中的“关闭”按钮时,会调用 closeView
方法。此方法检查委托是否响应dismissPopoverAnimated:animated
,如果是,则调用它。如果它不响应此方法,它将显示一条日志消息并且什么也不做(因此它不会崩溃)。
我使用 ARC 编写代码,因此没有内存管理。
希望对你有所帮助。
【讨论】:
以上是关于ipad - 关闭 UIPopoverController的主要内容,如果未能解决你的问题,请参考以下文章
适用于 iPad 的 UINavigationController [关闭]