【IOS笔记】Creating Custom Content View Controllers

时间:2021-10-16 04:02:38

Creating Custom Content View Controllers

自定义内容视图控制器

Custom content view controllers are the heart of your app. You use them to present your app’s unique content. All apps need at least one custom content view controller. Complex apps divide the workload between multiple content controllers.

自定义内容视图控制器是应用程序的心脏。你使用它们来呈现应用程序的独特内容。所有的应用程序至少需要一个自定义内容视图控制器。复杂的应用程序把工作分成多个内容控制器。

A view controller has many responsibilities. Some of these responsibilities are things that iOS requires the view controller to do. Other responsibilities are things you assign to the view controller when you define its role in your app.

视图控制器有很多职责。 其中一些是iOS要求视图控制器来完成的。其它职责是当你在应用程序中定义它的角色时你需要分配给视图控制器的。

Anatomy of a Content View Controller  内容视图控制器的结构

The UIViewController class provides the fundamental infrastructure for implementing all custom view controllers. You define a custom subclass ofUIViewController. That subclass provides the necessary code to populate views with data and respond to user actions. When you want to make adjustments to the default behavior of the view controller, you override methods of the UIViewController class. Your view controller may also interact with other UIKit classes to implement the behavior you want.

UIViewController类提供了实现所有自定义视图控制器的基础结构。 你定义一个UIViewController类的子类。那个子类提供了必要的代码来用数据填充视图并响应用户动作。当你想对视图控制器的默认行为做调整时,你可以重载UIViewController类的方法。你的视图控制器还可能跟其它UIKit类交互来实现你想要的行为。

Figure 3-1 shows some of the key objects associated directly with a content view controller. These are the objects that are essentially owned and managed by the view controller itself. The view (accessible via the view property) is the only object that must be provided, although most view controllers have additional subviews attached to this view as well as custom objects containing the data they need to display.

图3-1 显示了一些直接跟一个内容视图控制器相关的主要对象。这些对象都是视图控制器本身基本上拥有并管理的对象。视图(可通过view属性访问)是必须提供的唯一对象,尽管大多数视图控制器都有额外的子视图连接到该视图。一个内容视图控制器还包含需要显示的数据的自定义对象。

Figure 3-1  Anatomy of a content view controller

【IOS笔记】Creating Custom Content View Controllers

When you design a new view controller, it potentially has many responsibilities. Some of those responsibilities look inward, to the views and other objects it controls. Other responsibilities look outward to other controllers. The following sections enumerate many of the common responsibilities for a view controller.

当你设计一个新的视图控制器,它可能有许多职责。其中一些职责在内部使用,给视图以及视图控制器控制的其它对象。其它职责面向其它控制器。以下章节枚举了很多视图控制器的通用职责。

View Controllers Manage Resources  视图控制器管理资源

Some objects are instantiated when the view controller is initialized and are disposed of when your view controller is released. Other objects, like views, are needed only when the view controller’s contents are visible onscreen. As a result, view controllers use resources efficiently and should be prepared to release resources when memory is scarce. Properly implementing this behavior in your app's view controllers makes it so your app uses memory and other resources—such as CPU, GPU, and battery—more efficiently.

一些对象在视图控制器被初始化时实例化,在视图控制器被丢弃时释放。其它对象,比如视图,只在视图控制器的内容在屏幕上可见时才被需要。因此,视图控制器有效地使用资源,并且应该准备好在内存不足时释放资源。在你的应用程序中正确地实现该行为,可让你的应用程序更有效地使用内存和其它资源---比如CPU, GPU, 以及电池。

See Resource Management in View Controllers.

View Controllers Manage Views  视图控制器管理视图

View controllers manage their view and its subviews, but the view’s frame—its position and size in its parent’s view—is often determined by other factors, including the orientation of the device, whether or not the status bar is visible and even how the view controller’s view is displayed in the window. Your view controller should be designed to layout its view to fit the frame provided to it.

视图控制器管理它们的视图以及其子视图,但是视图的边框(frame)---它的位置和在其父视图中的尺寸---常常由其它因素决定,包括设备的方向,状态栏是否可见或甚至是视图控制器的视图如何在窗口里被显示等。你的视图控制器应该设计布局它的视图来适应提供给它的边框(frame)。

View management has other aspects as well. Your view controller is notified when its view is about to appear and disappear from the screen. Your view controller can use this notification to perform other actions necessary to its operation.

视图管理还有其它方面。当视图控制器的视图即将从屏幕显示或消失时,它会被通知。你的视图控制器可以使用该通知来执行对其操作来说必要的其它动作。

See Resizing the View Controller’s ViewsSupporting Multiple Interface OrientationsResponding to Display-Related Notifications.

View Controllers Respond to Events   视图控制器响应事件

Your view controller is often the central coordinating object for its views and controls. Typically, you design your user interface so that controls send messages to the controller when a user manipulates them. Your view controller is expected to handle the message, making any necessary changes to the views or data stored in the view controller.

你的视图控制器常常是其视图和控件的*协调对象。通常情况下,你设计的用户界面以便控件在用户操作它们时给控制器发送消息。你的视图控制器需要处理消息,对视图或存储在视图控制器中的数据做必要的改变。

Your view controller also participates in the responder chain used to deliver events to your app. You can override methods in your view controller class to have it participate directly in event handling. View controllers also are good objects to implement other behaviors—such as responding to system notifications, timers or events specific to your app.

视图控制器还参与用来给应用程序发送事件的响应链。你可以在视图控制器类里重载方法来让其直接参与事件处理。视图控制器还是实现其它行为的好对象---比如响应系统通知,定时器或应用程序特定的事件。

See Using View Controllers in the Responder Chain.

View Controllers Coordinate with Other Controllers  视图控制器协调其它控制器

Although a view controller may create and manage many other objects, it does not usually need to expose these objects publicly to inspection or modification. It may collaborate with other objects (especially other view controllers), but it should expose the fewest number of properties and methods necessary to allow its collaborators to communicate with it. Exposing too many implementation details in your view controller class makes it difficult to modify your view controller’s implementation. Collaborators that rely on these implementation details would need to be modified to continue to work with your view controller class.

尽管一个视图控制器可能创建并管理很多其它对象,它通常并不需要公开暴露这些对象来检查或修改。它可能跟其它对象(特别是其它视图控制器)合作,但是它应该暴露最少数量的数学和必要方法来让它的合作者(collaborators)跟它交流。在视图控制器类中暴露太多的实现细节让修改视图控制器的代码变得困难。依赖这些实现细节的合作者可能需要*修改以继续能与你的视图控制器类一起工作。

See Coordinating Efforts Between View Controllers.

View Controllers Often Work with Containers   视图控制器常常跟容器一起工作

If your view controller is placed inside a container view controller, the container imposes additional constraints, as shown in Figure 3-2. The container may ask your view controller to provide other objects used to configure the container’s user interface. For example, a content view controller placed inside a tab view controller provides a tab bar item to display for that tab.

如果你的视图控制器被放置在一个容器视图控制器中,容器施加(impose)了额外的限制,见图3-2. 容器可能要求你的视图控制器提供配置容器用户界面的其它对象。比如,一个放置在标签视图控制器内的内容视图控制器提供了一个标签栏来显示标签。

Figure 3-2  A container view controller imposes additional demands on its children【IOS笔记】Creating Custom Content View Controllers

The properties used to configure the containers provided by UIKit are defined by the UIViewController class. For more information on specific types of containers and the properties you configure to support them, see View Controller Catalog for iOS.

配置UIKit提供的容器的属性由UIViewController 类定义。关于容器特定类型以及你可以配置的属性的更多信息,请看View Controller Catalog for iOS.

View Controllers May Be Presented by Other View Controllers   视图控制器可能被其它视图控制器呈现

Some view controllers you design are intended to be presented by other view controllers. You might present your view controller directly, or you might make it a child of a container view controller and present the container instead. When presented, it moves onscreen, remaining there until it is dismissed.

一些你设计的视图控制器打算让别的视图控制器来呈现。你可能直接呈现你的视图控制器,或者你可能让它成为一个容器视图控制器的子视图控制器,并呈现该容器。当它被呈现时,它显示在屏幕上直到它被丢弃。

There are several reasons you might present a view controller:以下是你可能呈现一个视图控制器的一些原因:

  • To gather information from the user immediately.为了立即从用户那收集信息。

  • To present some content temporarily.为了暂时呈现一些内容。

  • To change work modes temporarily.为了暂时改变工作模式。

  • To implement alternate interfaces for different device orientations.为不同的设备方向实现替换界面。

  • To present a new view hierarchy with a specific type of animated transition (or no transition).为了呈现一个带有一种特定动画过渡类型(或没有过渡)的新视图层次结构。

Most of these reasons involve interrupting your app’s workflow temporarily in order to gather or display some information. In almost all cases, the presented view controller implements a delegate. The presented view controller uses the delegate to communicate with the presenting view controller. After your app has the information it needs (or the user finishes viewing the presented information), the presented view controller communicates this back to the presenting view controller. The presenting view controller dismisses the presented view controller to return the app to its previous state.

大多数这些原因都设计短暂地打断应用程序的工作流以收集或显示一些信息。在几乎所有的情况当中,被呈现的视图控制器实现一个委托。被呈现的视图控制器使用委托来跟呈现它的视图控制器交流。当你的应用程序拥有了它需要的信息之后(或者用户结束查看被呈现的信息),被呈现的视图控制器把这些信息传回给呈现它的视图控制器。呈现它的视图控制器丢弃被呈现的视图控制器来让应用程序返回它的前一个状态。

See Presenting View Controllers from Other View Controllers.

Designing Your Content View Controller   设计你的内容视图控制器

Before writing any code in your view controller, you should be able to answer some basic questions about how you intend to use it. The questions provided below are designed to help you narrow the focus of your view controller and to help you understand the role it plays in your app. In particular, it helps you identify connections—usually to other controllers—your view controller needs to perform its tasks.

在你的视图控制器中编写任何代码之前,你应该能够回答一些关于你打算怎么使用它的基本问题。以下提供的问题,旨在帮助你缩小你的视图控制器的焦点,并帮助你理解它在应用程序中所扮演的角色。特别是,它帮助你识别你的视图控制器需要来执行它的各种任务的连接---通常是连到别的视图控制器的。

  • Are you using a storyboard to implement the view controller?你是否使用了一个故事板来实现视图控制器?

  • When is it instantiated?它在什么时候被实例化?

  • What data does it show?它显示什么数据?

  • What tasks does it perform?它需要执行什么任务?

  • How is its view displayed onscreen?它的视图是如何显示在屏幕上的?

  • How does it collaborate with other view controllers?它如何跟别的视图控制器发生合作?

Your answers to these questions need not be precise if you are still working out the role it plays. Still, it helps to have a general sense of what your view controller does and how other objects interact with it.

如果你正在了解它所扮演的角色,你对这些问题的答案不必精确。 尽管如此,它有助于让你对视图控制器做什么以及其它对象如何与它发生交互有一个基本的概念。

The questions above don’t ask you to define the appearance of your view controller or to be precise about the implementation details of how it performs the tasks you’ve assigned to it. Those are important questions you need to answer, but neither of these things should affect your view controller’s public interface. You want the flexibility to be able to change the visual design of your view controller without changing the class declaration that defines how other controllers collaborate with it.

以上问题不是要求你定义视图控制器的外形或者精确定义它如何执行你分配给它的任务的实现细节。那些都是你需要回答的重要问题,但是没有任何问题应该影响到视图控制器的公共接口(public interface)。你想要灵活性来让视图控制器能够改变它的视觉设计,但是不改变类的声明,这些声明定义了其它控制器如何跟它协作。

Use a Storyboard to Implement Your View Controller  使用一个故事板来实现你的视图控制器

You might consider whether or not to use a storyboard as an implementation detail, but the approach you take affects how you implement the view controller and how other objects collaborate with it. You always use a storyboard unless you have a strong reason not to.

你可能会考虑一个实现细节:是否使用一个故事板,但是你采用的方法会影响你如何实现视图控制器以及其它对象如何跟它协作。你应该总是使用一个故事板除非你有一个强烈原因不能这么做。

When you use storyboards:当你使用故事板时:

  • iOS usually instantiates your view controller for you automatically. iOS通常自动为你初始化视图控制器。

  • To finish instantiating it, you override its awakeFromNib method.要想结束实例化它,你可以重载它的awakeFromNib 方法。

  • Other objects configure it through its properties. 其它对象通过它的属性来配置它。

  • You create its view hierarchy and other related objects in Interface Builder. These objects are loaded automatically when the view is needed.你创建它的视图层次结构和界面中的其它相关对象。这些对象在视图被需要时会自动被加载。

  • Relationships with other view controllers are created in the storyboard.跟其它视图控制器之间的关系被创建在故事板中。

If you design your view controller to be used programmatically: 如果你通过程序设计你的视图控制器:

  • The view controller is instantiated by allocating and initializing it.视图控制器通过分配和初始化来实例化。

  • You create an custom initialization method to initialize the view controller.你创建一个自定义初始化方法来初始化视图控制器。

  • Other objects configure the view controller using its initialization method and by configuring its properties.其它对象使用视图控制器的的初始化方法以及通过配置它的属性来配置视图控制器。

  • You override the loadView method to programmatically create and configure its view hierarchy.你重载 loadView 方法来程序性创建和配置它的视图层次结构。

  • Relationships with other view controllers are created by writing code.跟其它视图控制器之间的关系通过写代码来创建。

Know When Your Controller Is Instantiated   了解你的视图控制器何时被实例化。

Knowing when your view controller is instantiated usually implies other details for how your app operates. For example, you might know that your view controller is always instantiated by the same object. Often the objects that instantiate view controllers are themselves view controllers; this is almost always the case in an app that uses storyboards. In any case, knowing when, why, and by what object your view controller is instantiated gives you insight into the information exchanged between your view controller and the object that created it.

了解视图控制器何时被实例化通常意隐含了你的应用程序如何操作的细节。比如,你可能知道你的视图控制器总是由同一个对象实例化。通常实例化视图控制器的对象本身就是视图控制器;这几乎总是在使用故事板的应用中出现的情况。 在任何时候,了解你的视图控制器何时,为什么,以及通过什么对象实例化等可以让你洞察视图控制器和创建它的对象之间的信息交互过程。

Know What Data Your View Controller Shows and Returns   了解你的视图控制器显示什么数据以及返回什么数据

When you answer these two questions, you are working to understand the data model for your app and also whether that data needs to be exchanged between your view controllers.

当你回答这两个问题时,你就是在理解应用程序的数据模型,以及是否有数据需要在视图控制器之间被交换。

Here are some common patterns you should expect to see in your view controllers:以下是几种你应该能在你的视图控制器中遭遇的通用模式:

  • The view controller receives data from another controller and displays it, without offering a way to edit it. No data is returned.视图控制器从另一个控制器接收数据并显示它,不对数据进行编辑。没有返回数据。

  • The view controller allows the user to enter new data. After the user finishes editing the data, it sends the new data to another controller.视图控制器允许用户输入新数据。当用户完成数据编辑之后,它把新数据发送给另一个控制器。

  • The view controller receives data from another controller and allows the user to edit it. After the user finishes editing the data, it sends the new data to another controller.视图控制器从另一个控制器接收数据,并允许用户对它进行编辑。当用户完成数据编辑之后,它把新数据发送给另一个控制器。

  • The view controller doesn’t send or receive data. Instead, it shows static views.视图控制器不发送或接收数据。相反,它只显示静态视图。

  • The view controller doesn’t send or receive data. Instead, its implementation loads its data without exposing this mechanism to other view controllers. For example, the GKAchievementViewController class has built-in functionality to determine which player is authenticated on the device. It also knows how to load that player’s data from Game Center. The presenting view controller does not need to know what data is loaded or how it was loaded.视图控制器不发送或接收数据。作为替代,它的实现加载它的数据,但不给其它视图控制器暴露该机制。 比如,  GKAchievementViewController 类有内建功能用以确定哪个玩家(player)在设备上被认证。 它还知道如何从游戏中心(Game Center)加载那个玩家的数据。呈现视图控制器(presenting view controller)不需要知道什么数据被加载或它是如何被加载。

You are not constrained to use only these designs.

你不限于仅使用上面这些设计方式(译者注:其实也可称为视图控制器的“设计模式”)。

When data travels into or out of your view controller, consider defining a data model class to hold the data to be transferred to the new controller. For example, in Your Second iOS App: Storyboards, the master controller uses a BirdSighting object to send data associated with a sighting to the detail controller. Using an object for this makes it easier to update the data to include additional properties without changing the method signatures in your controller classes.

当数据进入或离开你的视图控制器时,考虑定义一个数据模型类来装载准备进入到新控制器的数据。比如,在Your Second iOS App: Storyboards 中, 主控制器使用一个BirdSighting 对象来发送明细控制器相关的数据。 使用一个这样的数据对象可以很容易就更新数据对象来增加新属性,而不需要改变控制器类中的方法签名(参数表)。

Know What Tasks Your Controller Allows the User to Perform  了解你的控制器允许用户执行什么任务

Some view controllers allow users to view, create, or edit data. Other view controllers allow users to navigate to other screens of content. And some allow users to perform tasks provided by the view controller. For example, the MFMailComposeViewController class allows a user to compose and sendemails to other users. It handles the low-level details of sending mail messages.

一些视图控制器允许用户查看,创建或编辑数据。其它视图控制器则允许用户来导航到其它内容屏幕。 甚至有一些控制器让用户来执行由视图控制器提供的任务。 比如 MFMailComposeViewController 类允许一个用户构建(compose) 和给其它用户发送邮件。它处理发送邮件消息的低层细节。

As you determine which tasks your view controller performs, decide how much control over those tasks your view controller exposes to other controllers. Many view controllers can perform tasks without exposing configuration data to other controllers. For example, the GKAchievementViewControllerclass displays achievements to the user without exposing any properties to configure how it loads or presents its data. TheMFMailComposeViewController class presents a slightly different scenario by exposing some properties that another controller can use to configure the initial content it displays. After that, a user can edit the content and send the email message without giving other controller objects a chance to affect that process.

当你决定你的视图控制器执行哪个任务之后,决定你的视图控制器有多少控件(control)控制这些施加到其它控制器的任务。 很多视图控制器不需要给其它控制器施加配置数据就可以执行任务。比如,GKAchievementViewController 类给用户显示成就(achievements),它不需要任何属性来配置它如何加载或者呈现它的数据。MFMailComposeViewController 类则通过施加一些属性给另一个控制器让其可以配置它显示的初始内容,呈现一个稍有不同的方案。接着,用户可以编辑内容并发送email消息,不需要让其它控制器对象影响该过程。

Know How Your View Controller Is Displayed Onscreen  了解你的视图控制器如何被显示到屏幕上

Some view controllers are designed to be root view controllers. Others expect to be presented by another view controller or placed in a container controller. Occasionally, you design controllers that can be displayed in multiple ways. For example, a split view controller’s master view is displayed in the split view in landscape mode and in a popover control in portrait mode.

一些视图控制器被设计成是根视图控制器。其它视图控制器则期望由另一个视图控制器呈现或放置在一个容器控制器中。偶尔,你会设计能以多种方式显示的控制器。比如,一个分栏(split)视图控制器的主视图在横向模式中显示在分栏视图中,而在竖直模式中则显示在一个弹出控件中。

Knowing how your view controller is displayed gives you insight into how its view is sized and placed onscreen. It also affects other areas, such as determining what other controllers your view controller collaborates with.

了解你的视图控制器如何被显示让你洞察它的视图是如何被定尺寸以及如何被放置到屏幕上。 它还影响别的区域,比如决定你的视图控制器跟其它什么控制器发生合作。

Know How Your Controller Collaborates with Other Controllers   了解你的视图控制器如何跟别的控制器发生合作

By this point, you already know some things about collaboration. For example, if your view controller is instantiated from a segue, then it probably collaborates with the source view controller that configures it. And if your controller is a child of a container, then it collaborates with the container. But there are relationships in the other direction as well. For example, your view controller might defer some of its work and hand it off to another view controller. It might even exchange data with an existing view controller.

目前,你已经知道一些关于合作的事情。比如,如果你的视图控制器是从一个segue被实例化的,则它很可能跟配置它的源视图控制器发生合作。如果你的控制器是一个容器的子视图控制器,则它跟容器发生合作。 但是也还有其它方向的关系。比如,你的视图控制器可能推迟一些它的工作,并把它传递给另一个视图控制器。它甚至可能跟一个已经存在的视图控制器交换数据。

With all of these connections, your view controller provides an interface that other controllers use, or it is aware of other controllers and it uses their interfaces. These connections are essential to providing a seamless experience, but they also represent design challenges because they introduce dependencies between classes in your app. Dependencies are a problem because they make it more difficult to change any one class in isolation from the other classes that make up your app. For this reason, you need to balance the needs of your app now against the potential need to keep your app design flexible enough to change later.

使用这些所有的连接,你的视图控制器提供了一个界面供其它视图控制器使用,或者它意识到其它控制器并使用它们的界面。 为了提供流畅体验,这些连接是必不可少的,但是它们还代表了设计挑战,因为它们增加了应用程序中类之间的依赖关系。依赖关系是一个麻烦的问题,因为它们让任何一个类从组成应用程序的其它类中独立出来变得更加困难。因为这个原因,你需要平衡应用程序目前的需求和它的潜在需求来让应用程序为以后的改变保持足够的灵活性。

Examples of Common View Controller Designs   通用视图控制器设计实例

Designing a new view controller can be challenging. It helps to look at existing designs and understand what they do and why. This next section talks about some common view controller styles used in iOS apps. Each example includes a description of the role the view controller plays, a brief description of how it works at a high level, and one possible list of answers to the design questions listed above.

设计一个新视图控制器是具有挑战性的。 它有助于查看已经存在的设计以及理解它们多什么以及为什么。 以下章节讨论一些在iOS应用程序里通用的视图控制器风格。 每个实例都描述了视图控制器扮演的角色描述,简要说明它如何在高层工作,以及一个针对前述设计问题的答案列表。

Example: Game Title Screen   游戏标题屏幕

Mission Statement  任务声明

A view controller that allows the user to select between different styles of game play.

允许用户在不同游戏风格间做选择的视图控制器。

Description  描述

When a game is launched, it rarely jumps right into the actual game. Instead, it displays a title screen that identifies the game and presents a set of game variants to the player. For example, a game might offer buttons that allow a player to start a single player or multiplayer game. When the user selects one of the options, the app configures itself appropriately and launches into its gameplay.

当一个游戏被启动时,它很少直接跳入真实游戏。相反,它显示一个标题屏幕,该屏幕标识游戏并给用户呈现一组游戏变量。 比如,一个游戏可能提供按钮,让玩家选择单一玩家或多个玩家模式。 当用户选择了其中一个选项,应用程序进行适当的配置并进入它的游戏界面。

A title screen is interesting specifically because its contents are static; they don’t need data from another controller. As such, this view controller is almost entirely self-sufficient. It does, however, know about other view controllers, because it instantiates other view controllers to launch its gameplay.

标题屏幕很有趣,特别是因为它的内容都是静态的;它们不需要从另一个控制器获取数据。正因为如此,这个视图控制器几乎完全自给自足。然而,它确实知道其它视图控制器,因为它需要实例化其它视图控制器来启动它的玩法(gameplay)。

Design   设计

  • Are you using a storyboard to implement the view controller? Yes. 是否需要使用一个故事板来实现视图控制器?是的。

  • When is it instantiated? This view controller is the initial scene in the main storyboard.它什么时候被实例化?该视图控制器是主故事板中的初始场景。

  • What data does it show? This class displays preconfigured controls and images; it does not present user data. It does not include configurable properties.它显示什么数据?该类显示预配置控件和图像;它不呈现用户数据。它不包含可配置的属性。

  • What tasks does it perform? When a user taps on a button, it triggers a segue to instantiate another view controller. Each segue is identified so that the appropriate game play can be configured.它执行什么任务?当用户点击一个按钮时,它触发一个segue来实例化另一个视图控制器。每个segue都已被认证以便能配置适当的游戏场景。

  • How is its view displayed onscreen? It is installed automatically as the root view controller of the window. 它的视图如何被显示到屏幕?它像根视图控制器一样被自动载入。

  • How does it collaborate with other view controllers? It instantiates another view controller to present a gameplay screen. When gameplay ends, the other view controller sends a message to the title screen controller to inform it that play has ended. The title screen controller then dismisses the other view controller.它如何跟别的视图控制器发生合作?它实例化另一个视图控制器来呈现一个游戏屏幕。当游戏结束时,其它视图控制器给标题(title)屏幕控制器发送一个消息来通知它游戏已经结束,然后标题(title)屏幕控制器丢弃其它视图控制器。

Alternative Design Considerations  备选设计注意事项

The default answers assume that no user data is displayed. Some games include player data to configure the views or controls. For example:默认答案假设没有显示用户数据。某些游戏包含用户数据来配置视图或控件。比如:

  • You might want the view controller to display the user’s Game Center alias. 你可能想视图控制器来显示用户的游戏中心别名。

  • You might want it to enable or disable buttons based on whether the device is connected to Game Center.你可能想让它根据设备是否跟游戏中心连接来启用或禁用按钮。

  • You might want it to enable or disable buttons based on In-App Purchase items the user has purchased.你可能想根据用户购买的应用程序内部采购项目来启用或禁用按钮。

When these additional items are added to the design, the view controller takes on a more traditional role. It might receive data objects or data controllers from the app delegate so that it can query and update this state as necessary. Or, as it is the root view controller for the window, you might simply implement those behaviors directly in the title screen controller. The actual design likely depends on how flexible you need your code to be.

当这些附加项被添加到设计,视图控制器需要一个更加传统的角色。它可能从应用程序委托接收数据对象或数据控制器以便它能根据需要查询并更新该状态。 或者,就像用户窗口的根视图控制器,你可能直接在标题(title)屏幕控制器中简单实现那些行为。真实设计很可能依赖于如何保证你的代码的灵活性。

Example: Master View Controller  实例:主视图控制器

Mission Statement  任务声明

The initial view controller of a navigation controller, used to display a list of the app’s available data objects.

一个导航控制器的初始视图控制器,用来显示一系列应用程序的可用数据对象。

Description 描述

A master view controller is a very common part of a navigation-based app. For example, Your Second iOS App: Storyboards uses a master view to display the list of bird sightings. When a user selects a sighting from the list, the master view controller pushes a new detail controller onto the screen.

在基于导航的应用程序中,主视图控制器是一个非常通用的部分。比如,Your Second iOS App: Storyboards 使用一个主视图来显示鸟类观察列表。当用户从列表中选择了一个sighting, 主视图控制器把一个新具体控制器推送到屏幕。

Because this view controller displays a list of items, it subclasses UITableViewController instead of UIViewController.

因为该视图控制器显示了数据项列表,它用UITableViewController 子类代替UIViewController.

Design  设计

  • Are you using a storyboard to implement the view controller? Yes.你是否需要使用一个故事板来实现视图控制器?是的。

  • When is it instantiated? As the root view controller of a navigation controller, it is instantiated at the same time as its parent.它何时被实例化?跟一个导航控制器的根视图控制器一样,它跟它的父类同时被实例化。

  • What data does it show? A high-level view of the app’s data. It implements properties that the app delegate uses to provide data to it. For example, the bird watching app provides a custom data controller object to the master view controller.它显示什么数据?一个应用程序数据的高层视图。它实现应用程序委托用来给它提供数据所用的各种属性。比如,bird watching 应用程序提供了一个自定义数据控制器对象给主视图控制器。

  • What tasks does it perform? It implements an Add button to allow users to create new records.它执行什么任务?它实现一个添加(Add)按钮来让用户来创建新纪录。

  • How is its view displayed onscreen? It is a child of a navigation controller. 它的视图如何被显示到屏幕上?它是一个导航控制器的子控制器。

  • How does it collaborate with other view controllers? When the user taps on an item in the list, it uses a push segue to show a detail controller. When the user taps on the Add button, it uses a modal segue to present a new view controller that edits a new record. It receives data back from this modal view controller and sends this data to the data controller to create a new bird sighting.它如何跟别的视图控制器发生合作?当用户点击列表中的一个项,它使用一个推送segue来显示一个细节控制器(detail controller). 当用户点击Add 按钮, 它使用一个模型segue来呈现一个新视图控制器,该新控制器用来编辑一个新纪录。 它接收从该模型视图控制器中返回的数据,并发送该数据给数据控制器来创建一个新的bird sighting.

Alternative Design Considerations 备选设计注意事项

A navigation controller and an initial view controller is used when building an iPhone app. When designing the same app for the iPad, the master view controller is a child of a split view controller instead. Most other design decisions stay the same.

当你构建一个iPhone应用程序时,使用一个导航控制器和一个初始视图控制器。 当你为iPad设计同样一个应用程序时,主视图控制器是一个分栏视图控制器(split view controller)的子控制器。其他大多数的设计决策保持不变。

Example: Detail View Controller 明细视图控制器

Mission Statement  任务声明

A controller pushed onto a navigation stack to display the details for a list item selected from the master view controller.

被推送到一个导航栈的控制器,用来显示被选中列表项的具体细节。列表项位于主视图控制器。

Description 描述

The detail view controller represents a more detailed view of a list item displayed by the master view controller. As with the master view controller, the list appears inside a navigation bar interface. When the user finishes viewing the item they click a button in the navigation bar to return to the master view.

详情视图控制器表示一个列表项的更加具体的视图,该列表项由主视图控制器显示。 当带有主视图控制器时,列表在一个导航栏界面显示。当用户结束查看数据项时,他们点击导航栏中的按钮返回到主视图。

Your Second iOS App: Storyboards uses the UITableViewController class to implement its detail view. It uses a static table cells, each of which accesses one piece of the bird sighting data. A static table view is a good way to implement this design.

Your Second iOS App: Storyboards 使用 UITableViewController 类来显示它的详情视图。它使用一个静态表格单元,每个单元可访问bird sighting数据的一个片段。 静态表格视图是实现该设计的一个好方法。

Design  设计

  • Are you using a storyboard to implement the view controller? Yes.你是否使用一个故事板来实现视图控制器?是的。

  • When is it instantiated? It is instantiated by a push segue from the master view controller.它何时被实例化? 它通过一个推送segue从主视图控制器被实例化。

  • What data does it show? It shows the data stored in a custom data object. It declares properties configured by the source view controller to provide this data.它显示什么数据?它显示存储在一个自定义数据对象中的数据。 它声明了由源视图控制器配置的各种属性来提供该数据。

  • What tasks does it perform? It allows the user to dismiss the view.它执行什么任务?它允许用户丢弃视图。

  • How is its view displayed onscreen? It is a child of a navigation controller.其视图如何被显示到屏幕上?它是导航控制器的一个子控制器。

  • How does it collaborate with other view controllers? It receives data from the master view controller.它如何跟其它视图控制器发生合作?它从主视图控制器接收数据。

Alternative Design Considerations   备选设计注意事项

A navigation controller is most often used when building an iPhone app. When designing the same app for the iPad, the detail view controller is a child of a split view controller instead. Many of the other implementation details stay the same.

当你构建一个iPhone应用程序时,最经常使用导航控制器。 当你为iPad设计同样一个应用程序时,主视图控制器是一个分栏视图控制器(split view controller)的子控制器。很多其它实现细节保持不变。

If your app needs more custom view behavior, it might subclass the UIViewController class and implement its own custom view hierarchy.

如果你的应用程序需要更多自定义视图行为,它可能子类化UIViewController 类并实现它自己的自定义视图层次结构。

Example: Mail Compose View Controller   实例四:邮件撰写视图控制器

Mission Statement   任务声明

A view controller that allows the user to compose and send an email.

允许用户撰写和发送邮件的视图控制器。

Description   描述

The Message UI framework provides the MFMailComposeViewController class. This class allows a user to compose and send an email. This view controller is interesting because it does more than simply show or edit data—it actually sends the email.

Message UI框架提供了MFMailComposeViewController 类。该类允许用户撰写和发送邮件。该视图控制器很有趣,因为它不仅仅能显示或编辑数据---它实际上能发送邮件。

Another interesting design choice in this class is that it allows an app to provide an initial configuration for the email message. After the initial configuration has been presented, the user can override these choices before sending the mail.

该类的另一个有趣的设计选择是它它允许应用程序给邮件信息提供一个初始配置。 当初始配置已经被呈现后,用户可以在发送邮件之前重写这些选择。

Design   设计

  • Are you using a storyboard to implement the view controller? No.你是否使用一个故事板来实现视图控制器?不。

  • When is it instantiated? It is instantiated programmatically.它何时被实例化?它通过程序进行实例化。

  • What data does it show? It shows the various parts of an email message, including a recipients list, title, attachments and the email message itself. The class provides properties that allow another view controller to preconfigure the email message.它显示什么数据?它显示一个邮件信息的不同部分,包括收件人列表,标题,附件以及邮件信息本身。 该类提供允许另一个视图控制器预配置邮件信息的各种属性。

  • What tasks does it perform? It sends email.它执行什么任务?它发送邮件。

  • How is its view displayed onscreen? The view controller is presented by another view controller. 它的视图如何被显示到屏幕? 视图控制器由另一个视图控制器呈现。

  • How does it collaborate with other view controllers? It returns status information to its delegate. This status allows the presenting view controller to know whether an email was sent.它如何跟别的视图控制器发生合作?它返回状态信息给它的委托。 该状态允许呈现视图控制器(presenting view controller)了解一个邮件是否已经被发送。

Implementation Checklist for Custom Content View Controllers

自定义内容视图控制器检查表

For any custom content view controllers you create, there are a few tasks that you must have your view controller handle:

对于你创建的任何自定义内容视图控制器,你必须让你的视图控制器处理以下一些任务:

  • You must configure the view to be loaded by your view controller.你必须配置由视图控制器加载的视图。

    Your custom class may need to override specific methods to manage how its view hierarchy is loaded and unloaded. These same methods might manage other resources that are created at the same time. See Resource Management in View Controllers.自定义类可能需要加载特定方法来管理它的视图层次结构如何被加载或卸载。 这些同样的方法可能管理同时创建的其它资源。参见 “Resource Management in View Controllers.”

  • You must decide which device orientations your view controller supports and how it reacts to a change in device orientation; see Supporting Multiple Interface Orientations.你必须决定你的视图控制器支持哪些设备朝向以及当设备方向发生改变时它如何反应;参见“Supporting Multiple Interface Orientations.”

As you implement your view controller, you will likely discover that you need to define action methods or outlets to use with its views. For example, if the view hierarchy contains a table, you probably want to store a pointer to that table in an outlet so that you can access it later. Similarly, if your view hierarchy contains buttons or other controls, you probably want those controls to call an associated action method on the view controller. As you iterate through the definition of your view controller class, you may therefore find that you need to add the following items to your view controller class:

当你实现你的视图控制器时,你很可能将发现你需要定义视图的动作方法或输出口(outlet)。比如,如果视图层次结构包含一个表格,你可能想在输出口里存储一个指向该表格的指针,这样你就可以在稍候访问它。同样地,如果你的视图层次结构包含按钮或其它控件,你很可能想让那些控件调用视图控制器上的相关动作方法。 当你遍历视图控制器类中的定义时,你可能因此发现你需要添加以下items到你的视图控制器类:

  • Declared properties pointing to the objects containing the data to be displayed by the corresponding views    各种声明属性,它们指向各个对象,这些对象包含了由相关视图显示的数据。

  • Public methods and properties that expose your view controller’s custom behavior to other view controllers    公共方法和属性,它们向其它视图控制器揭露视图控制器的自定义行为。

  • Outlets pointing to views in the view hierarchy with which your view controller must interact   插座变量,它们指向视图层次结构中的各个视图,视图控制器必须跟这些插座变量发生交互。

  • Action methods that perform tasks associated with buttons and other controls in the view hierarchy 动作方法,它们执行跟在视图层次结构中的按钮和其它控件相关的任务。

Important: Clients of your view controller class do not need to know what views your view controller displays or what actions those views might trigger. Whenever possible, outlets and actions should be declared in a category inside your class’s implementation file. For example, if your class is namedMyViewController, you implement the category by adding the following declaration to MyViewController.m:

重要提示:视图控制器的客户端不需要知道视图控制器显示什么视图或者那些视图可能触发哪些动作。 任何时候只要可能,插座变量和动作都应该被声明在类的实现文件中的一个类别(category)中。 比如,如果你的类叫MyViewController,你添加以下声明到MyViewController.m中来实现类别:

@interface MyViewController()
// Outlets and actions here.
@end
@implementation MyViewController
// Implementation of the privately declared category must go here.
@end
 

When you declare a category without a name, the properties and actions must be implemented in the same implementation block as any methods or properties declared in your public interface. The outlets and actions defined in the private category are visible to Interface Builder, but not to other classes in your app. This strategy allows you to gain the benefits of Interface Builder without exposing your class’s secrets.

 当你声明一个没有名称的类别,属性和动作方法必须像在公共接口里的任何方法和属性一样在同一个实现块里实现。在似有类别里定义的输出口和动作方法在界面生成器(Interface Builder)里可见,但是对于应用程序中的其它类来说不可见。 该策略让你不需要暴露类的秘密就可以获取界面生成器的好处。

If another class needs access to your view controller’s functionality, add public methods and properties to access this functionality instead.

如果另一个类需要访问 视图控制器的功能,添加公共方法和属性来访问该功能。