如何使用MasterDetail应用程序模板更新DetailView

11

我刚刚开始使用分割视图来创建iPad应用程序。当我仅使用标准的MasterDetail应用程序模板(Xcode 4.2)创建项目时,它会创建一个MasterViewController和一个DetailViewController。模板有以下方法,当从弹出的表格(主细节视图控制器)选择行时会调用该方法:

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

if (!self.detailViewController) 
{
    self.detailViewController = [[DetailViewController alloc]        initWithNibName:@"DetailViewController" bundle:nil]; 
}
[self.navigationController pushViewController:self.detailViewController animated:YES];

现在我理解了,当你使用常规的导航控制器时,如果你正在为iPhone编程,只需像这样将另一个视图控制器推到栈上即可。然而,对于该模板,它只是将详细视图推到弹出窗口中,而不是更新已经存在的内容。我不明白需要更新什么来从弹出窗口(主详细视图)中选择某些内容,然后使detailView更新。

更新:

为了尝试和测试已经在DetailViewController中设置的“detailItem”,我注释了pushViewController并添加了以下内容:

//[self.navigationController pushViewController:self.detailViewController animated:YES];
self.detailViewController.detailItem = @"Test";

// setter in detailViewController
- (void)setDetailItem:(id)newDetailItem
{
    if (_detailItem != newDetailItem) {
        _detailItem = newDetailItem;

        // Update the view.
        [self configureView];
    }

    if (self.masterPopoverController != nil) {
        [self.masterPopoverController dismissPopoverAnimated:YES];
    }        
}

- (void)configureView
{
    // Update the user interface for the detail item.
    // detailDescriptionLabel.text is a IBOutlet to the label on the detailView
    if (self.detailItem) {
        self.detailDescriptionLabel.text = [self.detailItem description];
    }
}

根据这段代码,detailViewController上标签的文本应该被更新。 但是,当我在主视图控制器表格中点击项目时,什么也没有发生。

1个回答

8
有几种不同的方法可以实现。首先,像你说的那样,删除pushViewController调用(我不知道为什么苹果的模板会这样做...可能只是为了向你展示你可以吗?)。
接下来,让您的MasterViewController知道已经显示的DetailViewController。我通常在appDelegate中设置master.detailViewController = detailViewController
请记住,DetailViewController已经被显示,所以您不总是需要重新分配它(除非您要用其他视图替换它) 第一种选择 使用委托调用来设置信息。声明一个协议将信息传递给detailView,并以适当的方式显示它。在这里有一个更详细的教程描述这个过程。 第二种选择 传递一些数据给DetailViewController并重写setter方法以刷新detailView。在这里有一个更详细的教程描述这个过程。
// in DetailViewController    
- (void)setDetailItem:(id)newDetailItem {
        if (detailItem != newDetailItem) {
            [detailItem release];
            detailItem = [newDetailItem retain];

            // Update the view.
            navigationBar.topItem.title = detailItem;
        NSString * imageName = [NSString stringWithFormat:@"%@.png",detailItem];
        [self.fruitImageView setImage:[UIImage imageNamed:imageName]];
        }
    }

编辑: 再次查看模板,setDetailItem类型代码已经存在,但是该代码会创建一个全新的detailView,因此在splitViewController上可见的detailView根本没有改变。


你是指创建另一个detailView,而不是“真正”的detailView吗? - 5StringRyan
抱歉表述不够清晰。所谓“真正的”是指在AppDelegate中定义并添加到SplitViewController中的那个(因此,在横向屏幕和纵向全屏幕上实际可见的)。在模板中,他们正在创建一个全新的并将其添加到导航控制器中。 - Kevin
只是好奇,为什么要创建这个新的详细页面? 我的意思是,如果正在创建“新”的detailViewController对象,但没有将其推送到堆栈上,它有什么用处? 目前,在AppDelegate类中创建了一个“DetailViewController”属性,并一直在访问AppDelegate.detailViewController属性进行更新。 我想知道这是否是正确的方法... - 5StringRyan
此时,它确实没有任何作用。我能想到的唯一原因是苹果公司想向你展示可以将视图推送到 UIPopOver 导航栈中。你的解决方案不错,通过在根(主?)视图中引用 detailView,代码稍微更清晰了一些,但思路是相同的。如果这对你有效,请继续使用它。 - Kevin
我不确定你所说的在Root(Master)中有对detailView的引用是什么意思。提供一个属性,该属性引用MasterViewController类中的detailViewController对象? - 5StringRyan
没错,我指的是“指针引用”,但本质上是一样的。在模板中的MasterViewController已经有了DetailViewController属性,只是在[didSelect:]操作之前没有设置任何值。我只需确保它是公共的,然后将其设置为AppDelegate中的detailView即可。masterViewController.detailViewController = detailViewController - Kevin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接