Navigating a Data Hierarchy with Table Views

导航数据表视图层次

A common use of table views—and one to which they’re ideally suited—is to navigate hierarchies of data. A table view at a top level of the hierarchy lists categories of data at the most general level. Users select a row to “drill down” to the next level in the hierarchy. At the bottom of the hierarchy is a view (often a table view) that presents details about a specific item (for example, an address book record) and may allow users to edit the item. This section explains how you can map the levels of the data model hierarchy to a succession of table views and describes how you can use the facilities of the UIKit framework to help you implement such navigation-based apps.

表格视图常常被用来导航数据层次,而且它们很适合。在层次顶层的表格视图列出了总体的数据类别(categories of data)。用户选择一行来深入到层次的下一层。 层次的底层是一个视图(常常是一个表格视图)表示一个指定数据项的具体信息(比如,一个地址簿),并且可能让用户编辑它们。 本节讲述了你如何才能够把数据模型层次中的层映射到一连串的表格视图中,以及描述了如何使用UIkit框架的功能来帮你实现这样的基于导航的应用程序。

Hierarchical Data Models and Table Views

一、层次数据模型和表格视图

For a navigation-based app, you typically design your app data as a graph of model objects that is sometimes referred to as the app’s data model. You can then implement the model layer of your app using various mechanisms or technologies, including Core Data, property lists, or archives of custom objects. Regardless of the approach, the traversal of your app’s data model follows patterns that are common to all navigation-based apps. The data model has hierarchical depth, and objects at various levels of this hierarchy should be the source for populating the rows of a table view.

对于一个基于导航的应用程序,你通常要为你的应用程序数据设计一个模型对象图,有时候它也被称为应用程序的数据模型。 然后你可以使用不同的机制或技术实现应用程序的模型层,包括Core Data,属性列表,或自定义归档对象。 不管使用哪种方法,应用程序数据模型的遍历都遵循所有基于导航应用程序都通用的模式。 数据模型有层次深度,在该层次中不同层的对象应该是填充一个表格视图行的资源。

Note: To learn about the Core Data technology and framework, see Core Data Starting Point.

注意:要想学习关于Core Data 技术和框架,请看Core Data Starting Point.

 

The Data Model as a Hierarchy of Model Objects

1、数据模型作为模型对象的一个层次

A well-designed app factors its classes and objects in a way that conforms to the Model-View-Controller (MVC) design pattern. The app’s data model consists of the model objects in this pattern. You can describe model objects (using the terminology provided by the object modeling pattern) in terms of their properties. These properties are of two general kinds: attributes and relationships.

一个应用程序设计良好的因素是它的类和对象遵循MVC设计模式。 应用程序的数据模型是该模式中的对象模型。 你可以根据它们的特性描述模型对象(使用对象建模模式提供的术语)。这些特性一般有两种类型:属性和关系。

Note: The notion of “property” here is abstractly related to, but not identical with, the declared property feature of Objective-C. A class definition typically represents properties programmatically through instance variables and declared properties.

注意:这里的“property”概念抽象地跟Objective-C中的声明的特性功能有关联,但不完全相同。 类定义通常指通过程序实现的实例变量和声明的特性。

 

Attributes represent elements of model-object data. Attributes can range from an instance of a primitive class (for example, an NSStringNSDate, or UIColor object) to a C structure or a simple scalar value. Attributes are generally what you use to populate a table view that represents a “leaf node” of the data hierarchy and that presents a detail view of that item.

属性表示模型对象数据的元素。 属性的范围可以从一个原始类的实例(比如,一个NSStringNSDate, 或 UIColor 对象 ),到一个C结构或者一个简单的标量值。属性一般是你用来填充代表数据层次中一个叶节点的一个表格视图,以及用来呈现那个数据项的一个具体视图。

 

A model object may also have relationships with other model objects. It is through these relationships that a data model acquires hierarchical depth by composing an object graph. Relationships are of two general kinds in terms of cardinality: to-one and to-many. To-one relationships define an object’s relationship with another object (for example, a parent relationship). A to-many relationship, on the other hand, defines an object’s relationship with multiple objects of the same kind. The to-many relationship is characterized by containment and can be programmatically represented by collections such as NSArray objects (or, simply, arrays). An array might contain other arrays, or it could contain multiple dictionaries, which are collections that identify their contained values through keys. Dictionaries, in turn, can contain one or more other collections, including arrays, sets, and even other dictionaries. As collections nest in other collections, your data model can acquire hierarchical depth.

一个模型对象可能还跟别的模型对象有关系。数据模型通过这些关系构成一个对象图以取得它的层次深度。有两种基本关系:一对一 以及 一对多。 一对一关系定义了一个对象跟另一个对象的关系(比如,一个父关系)。 另一方面,一对多关系定义了一个对象跟多个同样类型对象之间的关系。一对多关系的特性是可以通过程序由集合表示,比如NSArray 对象,(或简单的数组)。 一个数组可能包含其他数组,或它能包含多个字典,字典是通过键来标识它们包含的内容的一种集合类型。 相反,字典可以包含一个或多个其它集合,包括数组,集,甚至是其它字典。 正如集合嵌套在其它集合,你的数据模型可以获得层次深度。

Table Views and the Data Model

2、表格视图和数据模型

The rows of a plain table view are typically backed by collection objects of the app’s data model; these objects are usually arrays. Arrays contain strings or other elements that a table view can use when displaying row content. When you create a table view (described in “Creating and Configuring a Table View”), it immediately queries its data source for its dimensions—that is, it requests the number of sections and the number of rows per section—and then asks for the content of each row. The data source fetches this content from an array in the appropriate level of the data-model hierarchy.

简朴表格视图的行通常跟应用程序数据模型的集合对象相绑定; 这些对象通常是数组。 数组包含了字符串或其它表格视图能在显示行内容时使用的元素。当你创建一个表格视图时(“Creating and Configuring a Table View” 中描述),它立即向它的数据源请求它的尺寸---就是说,它要求区(section)的数目以及每个区的行数---然后请求每行的内容。 数据源从数据模型层次中适当层上的数组中取回该内容。

In many of the methods defined for a table view’s data source and delegate, the table view passes in an index path to identify the section and row that is the focus of the current operation—for example, fetching content for a row or indicating the row the user tapped. An index path is an instance of the Foundation framework’s NSIndexPath class that you can use to identify an item in a tree of nested arrays. The UIKit framework extends NSIndexPath to add a sectionand a row property to the class. The data source should use these properties to map a section and row of the table view to a value at the corresponding index of the array being used as the table view’s source of data.

在表格视图的数据源和委托中定义的很多方法中,表格视图传递一个索引路径来标识发生当前操作的区和行---比如,取回一行内容或缩进用户点击的行。 索引路径是Foundation 框架的 NSIndexPath 的一个实例, 你可以使用它来标识嵌套数组树种的数据项。 UIKit 框架延伸了NSIndexPath ,给类添加了一个section 和一个 row 特性。数据源应该使用这些特性来映射表格视图的一个区和行到表格视图数据源数组中相关索引处的值。

Note: The UIKit framework extension of the NSIndexPath class is described in NSIndexPath UIKit Additions.

注意:UIKit框架对NSIndexPath类的扩展在NSIndexPath UIKit Additions中描述。

 

In the sequence of table views in Figure 3-1, the top level of the data hierarchy is an array of four arrays, with each inner array containing objects representing the trails for a particular region. When the user selects one of these regions, the next table view lists names identifying the trails within the selected array. When the user selects a particular trail, the next table view describes that trail using a grouped table view.

图3-1中的表格视图序列中,数据层次的顶层是一个包含有四个子数组的数组, 每个子数组包含了代表一个特殊区域的小径(trail)对象。 当用户选择了这些区域中的其中一个,下个表格视图列出被选择数组中的小径名称。 当用户选择一个特殊的小径,下一个表格视图使用一个分组表格视图描述该小径。

Figure 3-1  Mapping levels of the data model to table views

Note: You could easily redesign the app in Figure 3-1 to have only two table views. The first table view would be an indexed list of trails by region. The second table view would display the detail for a selected trail.

注意:你可以简单的重新设计图3-1中的应用程序,让它只包含两个表格视图。第一个表格视图应该是一个以区域为索引的小径索引列表。第二个表格视图显示被选择小径的具体内容。

 

View Controllers and Navigation-Based Apps

二、视图控制器和基于导航的应用程序

The UIKit framework provides a number of view controller classes for managing common user interface patterns in iOS. View controllers are controller objects that inherit from the UIViewController class. They are an essential tool for view management, especially when an app uses those views to present successive levels of its data hierarchy. This section describes how two subclasses of UIViewController, navigation controllers and table view controllers, present and manage a succession of table views.

在iOS中UIKit 框架提供了很多视图控制器类来管理通用用户接口模式。 视图控制器是从 UIViewController类继承而来的控制器对象。 它们是视图管理的必要工具, 特别是当一个应用程序使用那些视图来呈现其数据层次中连续的层时。本节描述了两个 UIViewController 类的子类:导航控制器 和表格视图控制器 如何呈现和管理一系列表格视图。

Note: This section gives an overview of view controllers to provide some background for the coding tasks discussed later in this document. To learn about view controllers in depth, see View Controller Programming Guide for iOS.

注意:本节给出了视图控制器的一个概述,以为本文档中稍候讨论的代码任务提供一些背景知识。要想深度学习视图控制器,请看View Controller Programming Guide for iOS.

 

Navigation Controllers

1、导航控制器

The UINavigationController class inherits from UIViewController, a base class that defines the common programmatic interface and behavior for controller objects that manage views in iOS. Through inheritance from this base class, a view controller acquires an interface for general view management. After it implements parts of this interface, a view controller can autorotate its view, respond to low-memory notifications, overlay “modal” views, respond to taps on the Edit button, and otherwise manage the view.

UINavigationController 类继承自UIViewController。UIViewController是一个基础类,为管理iOS视图的控制器对象们定义了通用程序接口和控制器行为。通过从该基础类继承,视图控制器获取了一个用来基本视图管理的接口。 当它实现该接口部分后,视图控制器就可以自动旋转它的视图,响应低内存通知,叠加“模型”视图,响应编辑按钮上的点击,以及其他视图管理操作。

A navigation controller maintains a stack of view controllers, one for each of the table views displayed (see Figure 3-2). It begins with what’s known as the root view controller. When the user taps a row of the table view (often on a detail disclosure button), the root view controller pushes the next view controller onto the stack. The new view controller’s table view visually slides into place from the right, and the navigation bar items are updated appropriately. When users tap the back button in the navigation bar, the current view controller is popped off the stack. As a consequence, the navigation controller displays the table view managed by the view controller that is now at the top of the stack.

导航控制器有一个视图控制器栈,栈中每项代表显示的表格视图(参见图3-2)。 它从根视图控制器开始。 当用户点击了表格视图中的一行(常常是一个详细扩展按钮),根视图控制器把下一个视图控制推送到栈。 新的视图控制器控制的表格视图直观地从右边滑入到位,并且导航栏数据项被响应的更新。 当用户点击导航栏中的返回按钮, 当前的视图控制器弹出栈。因此,导航控制器显示视图控制器管理的位于栈顶部的表格视图。

Figure 3-2  Navigation controller and view controllers in a navigation-based app

图3-2 基于导航的应用程序中的导航控制器和视图控制器

Navigation controller and table-view controllers in an application

Navigation Bars

2、导航栏

Navigation bars are a user-interface device that enables users to navigate a hierarchy of data. Users start with general, top-level items and “drill down” the hierarchy to detailed views showing specific properties of leaf-node items. The view below the navigation bar presents the current level of data. A navigation bar includes a title for the current view and, if that view is lower in the hierarchy than the top level, a back button on the left side of the bar; the back button is a navigation control that the user taps to return to the previous level. (The back button by default displays the title for the previous view.) A navigation bar may also have an Edit button—used to enter editing mode for the current view—or custom buttons for functions that manage content (see Figure 3-3).

导航栏是一个用户接口设备,它能让用户导航一个数据层次。 用户从基本的顶层数据项来时,然后深入层次到具体的视图。具体的视图显示叶节点的特定属性。 在导航栏下方的视图呈现当前层的数据。导航栏包含一个当前视图的标题,以及如果该视图在层次中的层低于顶层,导航栏左侧有一个返回按钮;返回按钮是一个导航控件,用户可以点击它来返回到前一层。(返回按钮默认显示前一视图的标题) 导航栏可能还有一个编辑按钮---用来让当前视图进入编辑模式---或自定义按钮用来管理内容的各种功能(参见图3-3)。

Figure 3-3  Navigation bars and common control items

图3-3 导航栏和常用控件项

Navigation bars and common control items

UINavigationController manages the navigation bar, including the items that are displayed in the bar for the view below it. A UIViewController object manages a view displayed below the navigation bar. For this view controller, you create a subclass of UIViewController or a subclass of a view controller class that the UIKit framework provides for managing a particular type of view. For table views, this view controller class is UITableViewController. For a navigation controller that displays a sequence of table views reflecting levels within a data hierarchy, you need to create a separate custom table view controller for each table view.

UINavigationController 管理导航栏, 包括用于下方视图的控件项也显示在导航栏上。UIViewController对象管理导航栏下方的显示的视图。对于该视图控制器,你创建一个UIViewController 的子类 或 由UIKit框架提供的用来管理视图特殊类型的视图控制器类的子类。对于表格视图,该视图控制器类是UITableViewController. 对于一个导航控制器,它在数据层次中显示一系列反应层的表格视图,你需要为每个表格视图分别创建一个自定义表格视图控制器。

The UIViewController class includes methods that let view controllers access and set the navigation items displayed in the navigation bar for the currently displayed table view. This class also declares a title property through which you can set the title of the navigation bar for the current table view.

UIViewController类包含让视图控制器访问并设置显示在导航栏中的导航项的各种方法。这些导航项用于当前显示的表格视图。该类还声明了一个title属性,通过它你可以为当前表格视图设置导航栏的标题。

Table View Controllers

3、表格视图控制器

Although you could manage a table view using a direct subclass of UIViewController, you save yourself a lot of work if instead you subclass UITableViewController. The UITableViewController class takes care of many of the details you would have to implement if you created a direct subclass of UIViewController to manage a table view.

尽管你可以通过直接成为UIViewController的子类来管理表格视图,但是如果你通过从UITableViewController继承可以减少很多工作。UITableViewController 类 带有很多你必须要实现的很多细节,这是你直接从UIViewController继承来管理表格视图所没有的。

The recommended way to create a table view controller is to specify it in a storyboard. The associated table view is loaded from the storyboard, along with the table view’s attributes, size, and autoresizing characteristics. The table view controller sets itself as the data source and the delegate of the table view.

创建一个表格视图控制器的推荐方法是在一个故事板中指定它。相关的表格视图从故事板中加载,同时加载表格视图的属性,尺寸,以及自动尺寸调整特性等。 表格视图控制把自己设置为数据源以及表格视图的委托。

Note: You can create a table view controller programmatically by allocating memory for it and initializing it with theinitWithStyle: method, passing in either UITableViewStylePlain or UITableViewStyleGrouped for the required table view style.

注意:你可以用方法initWithStyle:通过编程给它分配内存和初始化它来创建一个表格视图控制器,把表格视图风格UITableViewStylePlain 或 UITableViewStyleGrouped传递给方法。

 

When the table view is about to appear for the first time, the table view controller sends reloadData to the table view, which prompts it to request data from its data source. The data source tells the table view how many sections and rows per section it wants, and then gives the table view the data to display in each row. This process is described in “Creating and Configuring a Table View.”

当表格视图即将第一次显示,表格视图控制器给表格视图发送reloadData消息,它促使表格视图从它的数据源那里请求数据。 数据源告诉表格视图有多少区,以及每个分区有多少行,然后给表格视图提供数据让其显示每行。 该过程描述在 “Creating and Configuring a Table View.”

The UITableViewController class also performs other common tasks. It clears selections when the table view is about to be displayed and flashes the scroll indicators when the table finishes displaying. In addition, it responds properly when users tap the Edit button by putting the table view into editing mode (or taking it out of editing mode if users tap Done). The class exposes one property, tableView, which gives you access to the managed table view.

UITableViewController 类还执行其它常用任务。 当表格视图即将显示并且当表格结束显示滚动指示器闪烁时,它清除各个区。此外,当用户点击编辑按钮时,它能正确响应用户点击,让表格视图进入编辑模式(或者退出编辑模式,如果用户点击Done)。UITableViewControler类有一个属性,tableView,它让你可以访问它管理的表格视图。

Note: A table view controller supports inline editing of table view rows; if, for example, rows have embedded text fields in editing mode, it scrolls the row being edited above the virtual keyboard that is displayed. It also supports the NSFetchedResultsController class for managing the results returned from a Core Data fetch request.

注意:表格视图控制器支持表格视图行的内嵌编辑(inline editing);比如,如果在编辑模式下行中内嵌了文边字段,它把正在编辑的行滚动到虚拟键盘显示的上方。它还支持  NSFetchedResultsController 类来管理从一个Core Data fetch请求返回的结果。

 

The UITableViewController class implements the foregoing behavior by overriding loadViewviewWillAppear:, and other methods inherited from UIViewController. In your subclass of UITableViewController, you may also override these methods to acquire specialized behavior. If you do override these methods, be sure to invoke the superclass implementation of the method, usually as the first method call, to get the default behavior.

UITableViewController 类通过重写loadView, viewWillAppear:, 以及其他从UIViewController 继承的方法来实现上述行为。在你的UITableViewController子类中,你还可以重写这些方法来实现特殊行为。 如果你确实重写了这些方法,请确保包含了该方法的父类实现,通常作为第一个方法调用,来获取默认行为。

Note: You should use a UIViewController subclass rather than a subclass of UITableViewController to manage a table view if the view to be managed is composed of multiple subviews, only one of which is a table view. The default behavior of the UITableViewController class is to make the table view fill the screen between the navigation bar and the tab bar (if either are present).

注意:如果所管理的视图是由多个子视图组成,只有其中一个是表格视图时,你应该使用一个UIViewController子类而不是UITableViewController的子类来管理表格视图。UITableViewController 类的默认行为是让表格视图填充导航栏和标签栏(如果其中之一有存在的话)之间的屏幕。

If you decide to use a UIViewController subclass rather than a subclass of UITableViewController to manage a table view, you should perform a couple of the tasks mentioned above to conform to the human interface guidelines. To clear any selection in the table view before it’s displayed, implement the viewWillAppear: method to clear the selected row (if any) by calling deselectRowAtIndexPath:animated:. After the table view has been displayed, you should flash the scroll view’s scroll indicators by sending a flashScrollIndicators message to the table view; you can do this in an override of the viewDidAppear: method of UIViewController.

如果你决定使用一个UIViewController 子类替代UITableViewController子类来管理一个表格视图,你应该遵循人性化接口设计指南执行上面提到的两个任务。 要想在表格视图显示之前清除任何区(section),实现viewWillAppear: 方法通过调用deselectRowAtIndexPath:animated:方法来清除被选中的行(如果有)。 当表格视图已经显示之后,你应该通过给表格视图发送一个 flashScrollIndicators 消息来闪烁滚动视图的滚动指示器;你可以在重写 UIViewController 的 viewDidAppear: 方法中完成。

 

Managing Table Views in a Navigation-Based App

4、在一个基于导航的应用程序中管理表格视图

UITableViewController object—or any other object that assumes the roles of data source and delegate for a table view—must respond to messages sent by the table view in order to populate its rows, configure it, respond to selections, and manage editing sessions. In the rest of this document, you learn how to do these things. However, there are certain other things you need to do to ensure the proper display of a sequence of table views in a navigation-based app.

UITableViewController对象---或任何其它兼任表格视图数据源和委托的对象---都必须响应表格视图发送的各种消息,以填充它的行,配置它,响应区(sections),以及管理编辑会话。 在文档的剩余部分,你将学习如何实现这些事情。然而,在一个基于导航的应用程序中,你确实还需要完成其它事情来确保一系列表格视图的正确显示。

Note: This section summarizes view-controller and navigation-controller tasks, with a focus on table views. For a thorough discussion of view controllers and navigation controllers, including the complete details of their implementation, see View Controller Programming Guide for iOS and View Controller Catalog for iOS.

主要:本节总结了视图控制器 和导航控制器任务,还重点讲述了表格视图。关于视图控制器和导航控制器的详细讨论,包括实现他们的完整详情,请看 View Controller Programming Guide for iOS 以及 View Controller Catalog for iOS.

 

At this point, let’s assume that a table view managed by a table view controller presents a list to the user. How does the app display the next table view in the sequence?

这时,让我们假设一个表格视图控制器管理的表格视图给用户呈现了一个列表。应用程序如何显示序列中的下个表格视图?

When a user taps a row of the table view, the table view calls the tableView:didSelectRowAtIndexPath: ortableView:accessoryButtonTappedForRowWithIndexPath: method implemented by the delegate. (That latter method is invoked if the user taps a row’s detail disclosure button.) The delegate creates the table view controller managing the next table view in the sequence, sets the data it needs to populate its table view, and pushes this new view controller onto the navigation controller’s stack of view controllers. A storyboard provides the specification that allows UIKit to perform most of this work for you.

当用户点击表格视图中的一行,表格视图调用委托方法tableView:didSelectRowAtIndexPath: 或 
tableView:accessoryButtonTappedForRowWithIndexPath: 方法。(后者当用户点击行的详情扩展按钮时调用。)委托创建表格视图控制器,它管理序列中下个表格视图。委托还设置用来填充表格视图的数据,并且推送该新视图控制器到导航控制器的视图控制器栈中。故事板提供了规范允许UIKit为你执行大多数工作。

Storyboards represent the screens in an app and the transitions between them. The storyboard in a basic app may contain just a few screens, but a more complex app might have multiple storyboards, each of which represents a different subset of its screens. The storyboard example in Figure 3-4 presents a graphical representation of each scene, its contents, and its connections.

故事板代表应用程序中的屏幕,以及它们之间的过渡。一个基本应用程序中的故事板可能只有几个屏幕,但是一个更复杂的应用程序可能有多个故事板,每个故事板代表屏幕的一个不同子集。图3-4中的故事板例子显示了每个场景,它的内容,以及它的链接关系等图形表示。

Figure 3-4  A storyboard with two table view controllers

图 3-5 带有两个表格视图控制器的故事板

scene represents an onscreen content area that is managed by a view controller. (In the context of a storyboard, scene and view controller are synonymous terms.) The leftmost scene in the default storyboard represents a navigation controller. A navigation controller is a container view controller because, in addition to its views, it also manages a set of other view controllers. For example, the navigation controller in Figure 3-4 manages the master and detail view controllers, in addition to the navigation bar and the back button that you see when you run the app.

场景代表屏幕上的一个内容区域,它由一个视图控制器管理。(在故事板的上下文中,场景和视图控制器是同义词) 故事板中最左边的场景代表一个导航控制器。导航控制器是一个容器视图控制器,因为除了它的视图,它还管理一组其它视图控制器。 比如,Figure 3-4 中的导航控制器除了管理应用程序运行时你看到的导航栏和返回按钮,还管理了主视图控制器和详情视图控制器。

relationship is a type of connection between scenes. In Figure 3-4, there is a relationship between the navigation controller and the master scene. In this case, the relationship represents the containment of the master and detail scenes by the navigation controller. When the app runs, the navigation controller automatically loads the master scene and displays the navigation bar at the top of the screen.

关系是一种场景之间的连接类型。 在图3-4中,导航控制器和主场景之间存在一个关系。在本例中,关系代表导航控制器与主和详情场景之间的容器关系。当应用程序运行时,导航控制器自动加载主场景并在屏幕顶部显示导航栏。

segue represents a transition from one scene (called the source) to the next scene (called the destination). For example, in Figure 3-4, the master scene is the source and the detail scene is the destination. When you select the Detail item in the master list, you trigger a segue from the source to the destination. In this case, the segue is a push segue, which means that the destination scene slides over the source scene from right to left. As the detail screen is revealed, a back button appears at the left end of the navigation bar, titled with the previous screen’s title (in this case, “Master”). The back button is provided automatically by the navigation controller that manages the master-detail hierarchy.

segue(跳转)表示从一个场景(源)到下一个场景(目标)之间的过渡。比如,图3-4中,主场景是源,详情场景是目标。当你在主列表里选择了具体数据项,你就触发了从源到目标的一个跳转。在本例中,跳转是一个推送跳转,就是说目标场景从右到左滑到源场景上。当详情屏幕显示后,在导航栏的左边显示一个返回按钮,按钮标题是前一个屏幕的标题(在本例中是”Master“)。返回按钮由管理master-detail层次的导航控制器自动提供。

Storyboards make it easy to pass data from one scene to another via the prepareForSegue:sender: method of theUIViewController class. This method is called when the first scene (the source) is about to transition to the next scene (the destination). The source view controller can implement prepareForSegue:sender: to perform setup tasks, such as passing information to the destination view controller about what it should display in its table view. Listing 3-1shows one implementation of this method.

故事板通过UIViewController类的prepareForSegue:sender:方法让数据从一个场景传送到另一个场景变得简单。该方法在当第一个场景(源)即将过渡到下一个场景(目标)时调用。源视图控制器可以实现prepareForSegue:sender: 方法来执行启动任务,比如传送信息给目标视图控制器,让其知道该在它的表格视图里显示什么内容。列表3-1显示了该方法的一个实现。

Listing 3-1  Passing data to a destination view controller

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
  if ([[segue identifier] isEqualToString:@"ShowDetails"]) {
    MyDetailViewController *detailViewController = [segue destinationViewController];
    NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
    detailViewController.data = [self.dataController objectInListAtIndex:indexPath.row];
  }
}

A segue represents a one-way transition from a source scene to a destination scene. One of the consequences of this design is that you can use a segue to pass data to a destination, but you can’t use a segue to send data from a destination to its source. To solve this problem, you create a delegate protocol that declares methods that the destination view controller calls when it needs to pass back some data.

推送(segue)表示从一个源场景到目标场景的一个单向过渡。因此,该设计只能让你使用推送来传送数据到目标场景,而不能使用推送(segue)从目标场景传送数据到源场景。要想解决该问题,你需要创建一个委托协议,它声明了目标视图控制器在它需要回送一些数据时调用的方法。

Listing 3-2 shows one implementation of a protocol for passing data back to a source view controller.

列表 3-2 显示了一个协议的实现,该协议用来回送数据到一个源视图控制器。

Listing 3-2  Passing data to a source view controller

@protocol MyAddViewControllerDelegate <NSObject>
- (void)addViewControllerDidCancel:(MyAddViewController *)controller;
- (void)addViewControllerDidFinish:(MyAddViewController *)controller data:(NSString *)item;
@end
 
- (void)addViewControllerDidCancel:(MyAddViewController *)controller {
  [self dismissViewControllerAnimated:YES completion:NULL];
}
 
- (void)addViewControllerDidFinish:(MyAddViewController *)controller data:(NSString *)item {
  if ([item length]) {
    [self.dataController addData:item];
    [[self tableView] reloadData];
  }
  [self dismissViewControllerAnimated:YES completion:NULL];
}

Note: The full details of creating storyboards are described in Xcode User Guide. To learn more about using view controllers in storyboards, see View Controller Programming Guide for iOS.

注意:创建故事板的完整信息在Xcode User Guide 里详细描述。要想学习更多关于在故事板中使用视图控制器的内容,请看View Controller Programming Guide for iOS.

 

Design Pattern for Navigation-Based Apps

三、基于导航应用程序的设计模式

A navigation-based app with table views should follow these design best practices:

一个带有表格视图的基于导航的应用程序应该遵循这些最好的设计实践:

  • view controller (typically a subclass of UITableViewController), acting in the role of data source, populates its table view with data from an object representing a level of the data hierarchy.

    视图控制器(通常是UITableViewController 的一个子类),是数据源,从代表数据层次的一层的对象中获取数据填充它的表格视图。

    When the table view displays a list of items, the object is typically an array. When the table view displays item detail (that is, a leaf node of the data hierarchy), the object can be a custom model object, a Core Data managed object, a dictionary, or something similar.

    当表格视图显示一个数据项列表,对象通常是一个数组。当表格视图显示数据详情时(就是数据层次中的一个叶节点),对象可以是一个自定义模型对象,一个Core Data管理的对象,一个字典,或一些类似的对象。

  • The view controller stores the data it needs for populating its table view.

    视图控制器存储了需要用来填充其表格视图的数据。

    The view controller can use this data directly for populating the table view, or it can use it to fetch or otherwise obtain the necessary data. When you design your view controller subclass, you should define a property to hold this data.

    视图控制器可以使用该数据直接填充表格视图,或它能使用它来提取或用其它方法获得必要的数据。 当你设计你的视图控制器子类时,你应该定义一个属性(property)来hold这些数据。

    View controllers should not obtain the data for their table view through a global variable or a singleton object such as the app delegate. Such direct dependencies make your code less reusable and more difficult to test and debug.

    视图控制器不应该通过一个全局变量或一个单一对象比如应用程序委托来获取表格视图数据。这样直接的依赖使你的代码缺少可重用性,并且更难测试和调试。

  • The current view controller on top of the navigation-controller stack creates the next view controller in the sequence and, before it pushes it onto the stack, sets the data that this view controller, acting as data source, needs to populate its table view.

    位于导航控制器栈顶部的当前视图控制器创建序列中的下一个视图控制器,并且在把它推送到栈之前,设置作为数据源的视图控制器的数据,这些数据用来填充其表格视图。

posted on 2013-08-11 14:55  cainiaozhang  阅读(639)  评论(0编辑  收藏  举报