在 Apples MultipleDetailViews 示例中加载已初始化的 DetailViewControllers

发布于 2024-11-15 02:07:59 字数 3501 浏览 1 评论 0原文

Apple 在其 iOS 开发网站上提供了一个有关如何使用具有不同详细视图的 splitview 的示例(请参阅 MultipleDetailViews 示例)。在 RootViewController 中,每次单元格被选中时,都会初始化一个新的 DetailViewController:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {

/*
 Create and configure a new detail view controller appropriate for the selection.
 */
NSUInteger row = indexPath.row;

UIViewController <SubstitutableDetailViewController> *detailViewController = nil;

if (row == 0) {
    FirstDetailViewController *newDetailViewController = [[FirstDetailViewController alloc] initWithNibName:@"FirstDetailView" bundle:nil];
    detailViewController = newDetailViewController;
}

if (row == 1) {
    SecondDetailViewController *newDetailViewController = [[SecondDetailViewController alloc] initWithNibName:@"SecondDetailView" bundle:nil];
    detailViewController = newDetailViewController;
}

// Update the split view controller's view controllers array.
NSArray *viewControllers = [[NSArray alloc] initWithObjects:self.navigationController, detailViewController, nil];
splitViewController.viewControllers = viewControllers;
[viewControllers release];

// Dismiss the popover if it's present.
if (popoverController != nil) {
    [popoverController dismissPopoverAnimated:YES];
}

// Configure the new view controller's popover button (after the view has been displayed and its toolbar/navigation bar has been created).
if (rootPopoverButtonItem != nil) {
    [detailViewController showRootPopoverButtonItem:self.rootPopoverButtonItem];
}

[detailViewController release];
}

现在我的想法是,不必每次都初始化视图控制器,只需在 viewDidLoad (以及标题)中初始化控制器,并在单元格被选中时传递它们的引用:

rootviewcontroller 中 viewDidLoad 的一部分:

firstDetailViewController = [[FirstDetailViewController alloc] initWithNibName:@"FirstDetailView" bundle:nil];
secondDetailViewController = [[FirstDetailViewController alloc] initWithNibName:@"FirstDetailView" bundle:nil];

现在 tableView didselectrow 方法如下所示:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {

/*
 Create and configure a new detail view controller appropriate for the selection.
 */
NSUInteger row = indexPath.row;

UIViewController <SubstitutableDetailViewController> *detailViewController = nil;

if (row == 0) {
    detailViewController = firstDetailViewController;
}

if (row == 1) {
    detailViewController = secondDetailViewController;
}

// Update the split view controller's view controllers array.
NSArray *viewControllers = [[NSArray alloc] initWithObjects:self.navigationController, detailViewController, nil];
splitViewController.viewControllers = viewControllers;
[viewControllers release];

// Dismiss the popover if it's present.
if (popoverController != nil) {
    [popoverController dismissPopoverAnimated:YES];
}

// Configure the new view controller's popover button (after the view has been displayed and its toolbar/navigation bar has been created).
if (rootPopoverButtonItem != nil) {
    [detailViewController showRootPopoverButtonItem:self.rootPopoverButtonItem];
}

//[detailViewController release];
}

在横向模式下一切正常,但在纵向模式下,从第一个detailviewcontroller,到第二个,然后到第一个,然后想切换到第二个。出现以下消息:由于未捕获的异常“NSInvalidArgumentException”而终止应用程序,原因:“无法从没有窗口的视图中呈现弹出窗口。”

从昨天晚上开始,我就试图解决这个问题,但没有找到解决方案。有人有想法吗?

干杯,多米尼克

Apple presents on their iOS Development sites an example on how to use a splitview with different detailviews (see MultipleDetailViews Example). In the RootViewController eery time the cell gets selected, a new DetailViewController is initialized:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {

/*
 Create and configure a new detail view controller appropriate for the selection.
 */
NSUInteger row = indexPath.row;

UIViewController <SubstitutableDetailViewController> *detailViewController = nil;

if (row == 0) {
    FirstDetailViewController *newDetailViewController = [[FirstDetailViewController alloc] initWithNibName:@"FirstDetailView" bundle:nil];
    detailViewController = newDetailViewController;
}

if (row == 1) {
    SecondDetailViewController *newDetailViewController = [[SecondDetailViewController alloc] initWithNibName:@"SecondDetailView" bundle:nil];
    detailViewController = newDetailViewController;
}

// Update the split view controller's view controllers array.
NSArray *viewControllers = [[NSArray alloc] initWithObjects:self.navigationController, detailViewController, nil];
splitViewController.viewControllers = viewControllers;
[viewControllers release];

// Dismiss the popover if it's present.
if (popoverController != nil) {
    [popoverController dismissPopoverAnimated:YES];
}

// Configure the new view controller's popover button (after the view has been displayed and its toolbar/navigation bar has been created).
if (rootPopoverButtonItem != nil) {
    [detailViewController showRootPopoverButtonItem:self.rootPopoverButtonItem];
}

[detailViewController release];
}

Now my idea is instead of initialising the viewcontrollers everytime, just initialize the controllers in the viewDidLoad (and also header) and pass the references of them when the cell gets selected:

part of the viewDidLoad in the rootviewcontroller:

firstDetailViewController = [[FirstDetailViewController alloc] initWithNibName:@"FirstDetailView" bundle:nil];
secondDetailViewController = [[FirstDetailViewController alloc] initWithNibName:@"FirstDetailView" bundle:nil];

Now the tableView didselectrow method looks like this:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {

/*
 Create and configure a new detail view controller appropriate for the selection.
 */
NSUInteger row = indexPath.row;

UIViewController <SubstitutableDetailViewController> *detailViewController = nil;

if (row == 0) {
    detailViewController = firstDetailViewController;
}

if (row == 1) {
    detailViewController = secondDetailViewController;
}

// Update the split view controller's view controllers array.
NSArray *viewControllers = [[NSArray alloc] initWithObjects:self.navigationController, detailViewController, nil];
splitViewController.viewControllers = viewControllers;
[viewControllers release];

// Dismiss the popover if it's present.
if (popoverController != nil) {
    [popoverController dismissPopoverAnimated:YES];
}

// Configure the new view controller's popover button (after the view has been displayed and its toolbar/navigation bar has been created).
if (rootPopoverButtonItem != nil) {
    [detailViewController showRootPopoverButtonItem:self.rootPopoverButtonItem];
}

//[detailViewController release];
}

In landscape mode everything works fine, but when in portrait mode a get an error, when switching from the firstdetailviewcontroller, to the second, then to the first and then want to switch to the second. Following message occurs: Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Popovers cannot be presented from a view which does not have a window.'

Since yesterday evening I am trying to figure this out, but i do not find a solution. Anybody an idea?

Cheers, Dominik

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

酷炫老祖宗 2024-11-22 02:07:59

我有类似的问题,但我发现这个 post 演示了在设置 splitView 的视图控制器之前必须从先前的DetailView 中删除 leftBarButtonItem 的想法。这段代码为我解决了这个问题。

这是 TPoschel 编写的代码。

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {

// Retrieve the new detail view controller
UIViewController *detailViewController = [[self.allData objectAtIndex:indexPath.section] objectAtIndex:indexPath.row];

// Add the detail view controller to a navigation controller and set the bar style
UINavigationController *detailNavigationController = [[UINavigationController alloc] initWithRootViewController:detailViewController];
detailNavigationController.navigationBar.barStyle = [[NSUserDefaults standardUserDefaults] integerForKey:@"UIBarStyle"];

// Retrieve previous detail view controller and remove the leftBarButtonItem
UINavigationController *previousDetailNavigationController = [splitViewController.viewControllers objectAtIndex:1];
UIViewController *previousDetailViewController = [[previousDetailNavigationController viewControllers] lastObject];
previousDetailViewController.navigationItem.leftBarButtonItem = nil;

// Update the split view controller's view controllers array.
NSArray *viewControllers = [[NSArray alloc] initWithObjects:self.navigationController, detailNavigationController, nil];
splitViewController.viewControllers = viewControllers;

[detailNavigationController release];
[viewControllers release];

// Dismiss the popover if it's present.
if (popoverController != nil) {
    [popoverController dismissPopoverAnimated:YES];
}

// This sets the left bar to nil when in landscape and equal to "Menu" when in portrait.
// We need to remove rootPopoverButtonItem from the previous viewController...
detailViewController.navigationItem.leftBarButtonItem = rootPopoverButtonItem;

}

I had a similar issue, but I found this post that demonstrated the idea that you have to remove the leftBarButtonItem from the previous detailView before setting up the splitView's view controllers. This code fixed the issue for me.

This is the code from that written by TPoschel.

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {

// Retrieve the new detail view controller
UIViewController *detailViewController = [[self.allData objectAtIndex:indexPath.section] objectAtIndex:indexPath.row];

// Add the detail view controller to a navigation controller and set the bar style
UINavigationController *detailNavigationController = [[UINavigationController alloc] initWithRootViewController:detailViewController];
detailNavigationController.navigationBar.barStyle = [[NSUserDefaults standardUserDefaults] integerForKey:@"UIBarStyle"];

// Retrieve previous detail view controller and remove the leftBarButtonItem
UINavigationController *previousDetailNavigationController = [splitViewController.viewControllers objectAtIndex:1];
UIViewController *previousDetailViewController = [[previousDetailNavigationController viewControllers] lastObject];
previousDetailViewController.navigationItem.leftBarButtonItem = nil;

// Update the split view controller's view controllers array.
NSArray *viewControllers = [[NSArray alloc] initWithObjects:self.navigationController, detailNavigationController, nil];
splitViewController.viewControllers = viewControllers;

[detailNavigationController release];
[viewControllers release];

// Dismiss the popover if it's present.
if (popoverController != nil) {
    [popoverController dismissPopoverAnimated:YES];
}

// This sets the left bar to nil when in landscape and equal to "Menu" when in portrait.
// We need to remove rootPopoverButtonItem from the previous viewController...
detailViewController.navigationItem.leftBarButtonItem = rootPopoverButtonItem;

}

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文