IOS编程教程(十一):在故事板联线(Segue)中的不同视图控制器里传值

这是我们演示故事板系列的第二篇文章。在前一个教程中,我们介绍了故事板,那是一个在Xcode中方便设计友好用户界面的功能。如果你跟着教程走,从开始到现在,你应该已经建立了一个简单的菜单应用程序的导航界面。但是上一篇我们有一件事没讨论,那就是如何在通过联线(segue)连接的视图控制器中传值呢?

首先,让我们快速浏览一下我们已经完成了什么。在此之前,我们学会了使用故事板建立一个下面几件事情:

>插入一个视图控制器到导航控制器

>创建一个表视图并放入一些菜单数据

>使用segue(联线)从一个视图控制器到令一个视图控制器的切换

然后,下面是最后成品了。当应用程序启动时,它会显示一个食谱列表。点击其中的任何一个单元格会把你带到另外一个视图,也就是详细介绍视图,虽然我们什么也没加。

Receipe应用程序的详细控制器

菜单应用程序的详细信息控制器

我们没有实现详细视图,现在显示了一个静态的标签。因此,我们将继续努力,在这个项目上继续完善应用程序。

分配视图控制器类

前一个教程中,我们简单地创建一个视图控制器来作为菜单详细信息视图。默认情况下,视图控制器指定为UIViewController类。

让我们重新审视我们的问题。在视图中的标签应改变为相对于所选菜单。很明显,必须有用于存储菜单名称一个变量的UIViewController。

事实是UIViewController类提供了基本的视图管理模式。它对应于一个空白视图。没有任何变量分配给存储的食谱名。因此,而不是直接使用UIViewController,我们扩展它创建自己的类(称为UIViewController子类)。

在项目浏览器中,用鼠标右键单击“RecipeBook”文件夹并选择“New File ...”。

故事板新的视图控制器

在Xcode项目中创建新文件

选择“Objective-C类的类模板”下的Cocoa Touch的。

故事板新的ObjectiveC类

选择目标C类

将该类命名为为“RecipeDetailViewController”和它的一个子类“UIViewController”。请确保取消选中“with XIB for user interface(XIB用户界面)”的选项。我们正在使用演示板设计用户界面,我们不需要创建一个单独的界面生成器文件。单击“下步”,在你的项目文件夹中保存文件。

故事板RecipeDetailViewController类

创建一个RecipeDetailViewController的类(子类的UIViewController)

下一步,我们必须指定RecipeDetailViewController类的视图控制器。回到故事板编辑器和选择详细视图控制器。在身份检查,改变类的为“RecipeDetailViewController”。

“故事大纲”更改视图控制器类

更改视图控制器类

在自定义类里添加变量

我们刚刚创建从UIViewController类继承的自定义视图控制器类。但是,它和父类不同,因为我们可以添加我们自己的变量和方法。有一些事情,我们必须改变:

>声明变量(recipeName)来传递数据---当用户从菜单视图中选中菜单,必须有个方法把值传递到详细视图中。

>声明变量(recipeLabel)给文本标签--标签是静态的,必须用菜单名来更新。

好吧,让我们添加这些的两个的变量(recipeLabel和recipeName)。选择“RecipeDetailViewController.h”,并​​增加了两个属性的接口:

1
2
3
4
5
6
@interface RecipeDetailViewController : UIViewController

@property (nonatomic, strong) IBOutlet UILabel *recipeLabel;
@property (nonatomic, strong) NSString *recipeName;

@end

转到的“RecipeDetailViewController.m”,并添加下面变量。确保你的代码放在“@ implementation RecipeDetailViewController”下:

1
2
3
4
@implementation RecipeDetailViewController

@synthesize recipeLabel;
@synthesize recipeName;
如果您忘记了什么是接口(interface)和实现(implementation),回到本教程中,并重新审视这些概念。

建立变量与用户界面的连接

接下来,我们就将"recipeLabel"与可视化标签连接起来。在故事板编辑器,按命令键,然后单击“菜单详细信息视图 - 控制器”图标,将其拖动到标签对象。放开两个按钮,弹出一个显示变量的选择。选择变量“recipeLabel”。

故事板配方的详细信息链接变量

UI元素和变量之间建立连接

就是这样。现在你已经连接标签与变量。视觉上的任何变化将反映在变量上。但是,仍然有一件事情。我们希望有标签,以示菜单名称。因此,在viewDidLoad函数中,我们添加以下代码,设置标签文本与选中菜单名称相同。

1
2
3
4
5
6
- (void)viewDidLoad
{
    [super viewDidLoad];
    // Set the Label text with the selected recipe
    recipeLabel.text = recipeName;
}

尝试编译并运行您的应用程序。哎呀!详细信息视图中,选择任何配方后,是完全空白的。这是预期的行为。因为我们没有写任何代码来传递的菜单名称。因此,“recipeName”变量是空的,空的文本标签。

Receipe空的详细信息控制器的应用程序

Receipe为空的详细信息控制器的应用程序

使用联线(segue)来传递数据

现在到了教程的核心部分,有关如何使用Segue实现视图控制器之间的数据传递。Segues管理视图控制器之间的过渡。在此之上,SEGUE对象是用来准备从一个视图控制器过渡到另一个。当SEGUE被触发,视觉过渡发生之前,演示图板运行时调用prepareForSegue:sender:当前视图控制器的方法(在我们的例子中,这是RecipeBookViewController)。通过实施这一方法,我们可以将任何需要的数据传递到要显示的视图控制器中

然而,最好的做法是给每条联线(segue)赋予一个独特的标识符(unique identifier。这个标识符是一个字符串,应用程序使用它以区分不同的联线(SEGUE)。您的尤其当应用程序变得更加复杂,很可能你将有一个以上的联线来连接视图控制器的时候,就尤为必要。

要指定标识符,选择联线(SEGUE),并在标志检查(identity inspector)将其设置。让我们命名那根联线(SEGUE)为 “sh​​owRecipeDetail”。

故事板Segue公司标识

故事板Segue公司标识

接下来,我们将在源代码中实现prepareForSegue:sender:方法“食谱 - 视图 - 控制器。选择“RecipeBookViewController.m”,并添加下面的代码:

1
2
3
4
5
6
7
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    if ([segue.identifier isEqualToString:@"showRecipeDetail"]) {
        NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
        RecipeDetailViewController *destViewController = segue.destinationViewController;
        destViewController.recipeName = [recipes objectAtIndex:indexPath.row];
    }
}

联线控制的界面跳转开始时,prepareForSegue方​​法会被调用。第一线是用来验证联线标识符。在这种情况下,判断联线标识符是否为“showRecipeDetail”。第二行代码调用的tableView:indexPathForSelectedRow的检索选定的表行。第三行,得到跳转的目标视图,这里为RecipeDetailViewController。最后行,得到选定表行的行数,用行数得到选定菜单数据,赋值给目标视图的变量recipeName。由于先前把recipeName变量的值赋给标签,故详细视图可以显示菜单名。

但是您不能运行你的应用程序。在复制和粘贴上面的方法到RecipeBookViewController.m,您应该会看到一些错误。

故事板prepareForSegue错误

prepareForSegue错误

如上图所示,有三个错误。但是我们可以归纳为两种:

>RecipeBookViewController没有找到tableView

>什么是RecipeDetailViewController?Xcode,不知道它是什么。

让我们先谈第二个错误。对应RecipeBookViewController,它不知道有关RecipeDetailViewController的信息。在Objective C中,您可以使用“#impoet”指令来导入其他类的头文件。导入头文件“RecipeDetailViewController.h”,RecipeBookViewController可以访问详细信息视图控制器属性和方法的。在开始的时候添加将下面的代码来修复错误:

1
#import “RecipeDetailViewController.h”

关于第一个错误,你应该知道如何解决它。这是我们前面讨论过的标签UI元素。应该有一个相应的变量tableView连接的UI变量。

因此,在的RecipeBookViewController.h,添加下面的代码“@end”之前:

1
@property (nonatomic, strong) IBOutlet UITableView *tableView;

对于RecipeBookViewController.m,添加的合成指令告诉编译器生成的tableView变量的存取方法。

1
2
3
4
5
@implementation RecipeBookViewController {
    NSArray *recipes;
}

@synthesize tableView; // Add this line of code

最后,回到故事板把变量和UI元素连接起来。在“食谱 - 视图 - 控制器”,按住Command键并单击视图控制器图标,将其拖动到表视图。松开左键选择“tableView”

故事板连接泰伯维

建立连接的tableView变量

现在,所有的错误应该得到解决。让我们尝试编译和运行的应用程序。这个时候,你的应用程序应该按预期工作显示。尽量选择任何菜单,可看到详细视图显示所选项目的名称。

配方正确的详细信息视图的应用程序

菜单应用程序 - 我们的最终交付

接下来会发生什么呢?

建立一个应用程序的导航界面,是不是很容易吗?随着故事板的推出,大大减少了你需要的代码来处理。最重要的是,集中式的故事板流给应用程序接口提供了一个高层次的构建平台。我希望这两个教程,让你知道故事板的工作原理,以及你可以利用它来构建自己的应用程序。虽然我们已经创建的应用程序很简单,举一个简单的UI,并阐述基本概念,您可以依据它来建立更复杂的应用程序。

在以后的教程中,我们将探讨的静态表格单元格,并继续使应用程序甚至更好的选项卡控制器,敬请关注,

posted @ 2012-11-25 14:56  但,我知道  阅读(5572)  评论(3编辑  收藏  举报