国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 學(xué)院 > 開(kāi)發(fā)設(shè)計(jì) > 正文

Mac應(yīng)用編程指南之三——核心應(yīng)用設(shè)計(jì)

2019-11-09 15:38:56
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

The Core App Design

核心應(yīng)用設(shè)計(jì)

To unleash the power of OS X, you develop apps using the Cocoa application environment. Cocoa PResents the app’s user interface and integrates it tightly with the other components of the Operating system. Cocoa provides an integrated suite of object-oriented software components packaged in two core class libraries, the AppKit and Foundationframeworks, and a number of underlying frameworks providing supporting technologies. Cocoa classes are reusable and extensible—you can use them as is or extend them for your particular requirements.

使用Cocoa應(yīng)用程序環(huán)境來(lái)開(kāi)發(fā)應(yīng)用,以釋放OS X的強(qiáng)大性能。Cocoa呈現(xiàn)應(yīng)用的用戶(hù)界面,并將其與操作系統(tǒng)的其它組件整合為一體。Cocoa通過(guò)AppKit和Foundation框架這兩個(gè)核心類(lèi)庫(kù)來(lái)提供一套面向?qū)ο蟮能浖M件整合套裝,以及一些提供支持技術(shù)的底層框架。Cocoa類(lèi)可復(fù)用、可擴(kuò)展——你可以直接使用它們,也可以根據(jù)特殊需要來(lái)擴(kuò)展它們。

Cocoa makes it easy to create apps that adopt all of the conventions and expose all of the power of OS X. In fact, you can create a new Cocoa application project in Xcode and, without adding any code, have a functional app. Such an app is able to display its window (or create new documents) and implements many standard system behaviors. And although the Xcode templates provide some code to make this all happen, the amount of code they provide is minimal. Most of the behavior is provided by Cocoa itself.

Cocoa使創(chuàng)建既能適應(yīng)慣例、又能展現(xiàn)OS X能力的應(yīng)用變得簡(jiǎn)單。事實(shí)上,如果在Xcode中創(chuàng)建一個(gè)新的Cocoa應(yīng)用程序工程,幾乎不用添加任何代碼,就擁有了一個(gè)可用的應(yīng)用。這個(gè)應(yīng)用可以顯示它的窗口(或創(chuàng)建新的文檔),還能實(shí)現(xiàn)許多基本系統(tǒng)功能。為實(shí)現(xiàn)這些功能,盡管Xcode模板提供了一些代碼,但代碼的數(shù)量極少。大部分的功能是由Cocoa本身提供的。

To make a great app, you should build on the foundations Cocoa lays down for you, working with the conventions and infrastructure provided for you. To do so effectively, it's important to understand how a Cocoa app fits together.

創(chuàng)建精彩的應(yīng)用,需要建立在Cocoa鋪設(shè)的基礎(chǔ)之上,與為你提供的慣例和基礎(chǔ)設(shè)施協(xié)同工作。為更有效地做到這一點(diǎn),理解Cocoa應(yīng)用如何適配很重要。

Fundamental Design Patterns

基礎(chǔ)設(shè)計(jì)模式

Cocoa incorporates many design patterns in its implementation. Table 2-1 lists the key design patterns with which you should be familiar.

Cocoa在其實(shí)現(xiàn)中包含多種設(shè)計(jì)模式。表2-1列出了你應(yīng)當(dāng)熟悉的重要設(shè)計(jì)模式。

Table 2-1  Fundamental design patterns used by Mac apps

表2-1 Mac應(yīng)用使用的基礎(chǔ)設(shè)計(jì)模式

Design pattern

Why it is important

Model-View-Controller

模型-視圖-控制器

Use of the Model-View-Controller (MVC) design pattern ensures that the objects you create now can be reused or updated easily in future versions of your app.

使用模型-視圖-控制器(MVC)設(shè)計(jì)模式確保現(xiàn)在創(chuàng)建的對(duì)象在應(yīng)用的將來(lái)版本中很容易地復(fù)用和更新。

Cocoa provides most of the classes used to build your app’s controller and view layers. It is your job to customize the classes you need and provide the necessary data model objects to go with them.

Cocoa提供了構(gòu)建應(yīng)用控制器和視圖層的大多數(shù)類(lèi)。你的工作是定制需要的類(lèi)、提供與之協(xié)同的必要的數(shù)據(jù)模型。

MVC is central to a good design for a Cocoa application because many Cocoa technologies and architectures are based on MVC and require that your custom objects assume one of the MVC roles.

MVC對(duì)于一個(gè)好的Cocoa應(yīng)用設(shè)計(jì)來(lái)說(shuō),是居于中心位置的;這是由于Cocoa技術(shù)和架構(gòu)是基于MVC的,同時(shí)也要求自定義的對(duì)象也要扮演MVC中的一個(gè)角色。

Delegation

代理

The delegation design pattern allows you to change the runtime behavior of an object without subclassing. Delegate objects conform to a specificprotocol that defines the interaction points between the delegate and the object it modifies. At specific points, the master object calls the methods of its delegate to provide it with information or ask what to do. The delegate can then take whatever actions are appropriate.

代理設(shè)計(jì)模式允許你不必繼承一個(gè)對(duì)象,就可以在運(yùn)行時(shí)改變其行為。代理對(duì)象遵循特定的協(xié)議,這個(gè)協(xié)議在代理和它所修改的對(duì)象之間定義了交互點(diǎn)。在這些特定點(diǎn)上,控制對(duì)象調(diào)用其代理的方法為代理提供信息,或詢(xún)問(wèn)該做什么。然后代理可以采取任何合理的操作。

Responder chain

響應(yīng)者鏈

The responder chain defines the relationships between event-handling objects in your app. As events arrive, the app dispatches them to the first responder object for handling. If that object does not want the event, it passes it to the next responder, which can either handle the event or send it to its next responder, and so on up the chain.

響應(yīng)者鏈定義了應(yīng)用中事件處理對(duì)象之間的關(guān)系。當(dāng)事件到達(dá)時(shí),應(yīng)用把它們分派到第一響應(yīng)者進(jìn)行處理。如果這個(gè)響應(yīng)者不接收這個(gè)事件,它會(huì)傳遞到下一個(gè)響應(yīng)者——它或者處理事件,或者將其傳遞到下一個(gè)響應(yīng)者,依此類(lèi)推。

Windows and views are the most common types of responder objects and are always the first responders for mouse events. Other types of objects, such as your app’s controller objects, may also be responders.

窗口和視圖是最常見(jiàn)的響應(yīng)者類(lèi)型,同時(shí)也是鼠標(biāo)事件的第一響應(yīng)者。其它類(lèi)型的對(duì)象,比如應(yīng)用的控制器對(duì)象,也可以是響應(yīng)者。

Target-action

目標(biāo)-動(dòng)作

Controls use the target-action design pattern to notify your app of user interactions. When the user interacts with a control in a predefined way (such as by touching a button), the control sends a message (the action) to an object you specify (the target). Upon receiving the action message, the target object can then respond in an appropriate manner.

控件使用目標(biāo)-動(dòng)作設(shè)計(jì)模式來(lái)向應(yīng)用通知用戶(hù)交互。當(dāng)用戶(hù)通過(guò)預(yù)先定義的方式(比如按下按鈕)與控件進(jìn)行交互時(shí),控件會(huì)向你指定的對(duì)象(目標(biāo))發(fā)送消息(動(dòng)作)。當(dāng)收到動(dòng)作消息時(shí),目標(biāo)采取適當(dāng)?shù)姆绞竭M(jìn)行響應(yīng)。

Block objects

塊對(duì)象

Block objects are a convenient way to encapsulate code and local stack variables in a form that can be executed later. Blocks are used in lieu of callback functions by many frameworks and are also used in conjunction with Grand Central Dispatch to perform tasks asynchronously.

塊對(duì)象是一種把代碼和本地堆變量封裝起來(lái)以便稍后執(zhí)行的便捷方式。塊被許多框架用于回調(diào)功能的替代,同時(shí)也用于與GCD連接,異步執(zhí)行任務(wù)。

For more information about using blocks, see Blocks Programming Topics.

更多關(guān)于塊使用的信息,參考Blocks Programming Topics。

Notifications

通知

Notifications are used throughout Cocoa to deliver news of changes to your app. Many objects send notifications at key moments in the object’s life cycle. Intercepting these notifications gives you a chance to respond and add custom behavior.

通知貫穿于Cocoa,來(lái)向應(yīng)用傳遞變化的消息。許多對(duì)象在生命周期的重要時(shí)刻發(fā)送通知。攔截這些通知,可獲得響應(yīng)的機(jī)會(huì),來(lái)添加自定義行為。

Key-value observing (KVO)

鍵值觀察(KVO)

KVO tracks changes to a specific property of an object. When that property changes, the change generates automatic notifications for any objects that registered an interest in that property. Those observers then have a chance to respond to the change.

KVO跟蹤一個(gè)對(duì)象的某一特定屬性的變化。當(dāng)這個(gè)屬性變化時(shí),會(huì)自動(dòng)通知至所有已注冊(cè)為對(duì)這個(gè)屬性感興趣的對(duì)象。這些觀察者便擁有了一次響應(yīng)變化的機(jī)會(huì)。

Bindings

綁定

Cocoa bindings provide a convenient bridge between the model, view, and controller portions of your app. You bind a view to some underlying data object (which can be static or dynamic) through one of your controllers. Changes to the view are then automatically reflected in the data object, and vice versa.

Cocoa綁定在應(yīng)用的模型、視圖、控制器之間提供了方便的連接。可以通過(guò)控制器,將一個(gè)視圖綁定到底層的數(shù)據(jù)對(duì)象(可以是靜態(tài)的,也可以是動(dòng)態(tài)的)。視圖的變化會(huì)自動(dòng)反映到數(shù)據(jù)模型上,反之亦然。

The use of bindings is not required for apps but does minimize the amount of code you have to write. You can set up bindings programmatically or using Interface Builder.

綁定的使用不是必須的,但它的確可以最大程度地降低代碼量。可通過(guò)編程或使用界面生成器來(lái)設(shè)置綁定。

The App Style Determines the Core Architecture

應(yīng)用的風(fēng)格決定其核心架構(gòu)

The style of your app defines which core objects you must use in its implementation. Cocoa supports the creation of both single-window and multiwindow apps. For multiwindow designs, it also provides a document architecture to help manage the files associated with each app window. Thus, apps can have the following forms:

應(yīng)用的風(fēng)格決定了在其實(shí)現(xiàn)中必須使用的核心對(duì)象。Cocoa同時(shí)支持單窗口和多窗口應(yīng)用。對(duì)于多窗口應(yīng)用,它還提供了文檔架構(gòu),來(lái)管理連接到每個(gè)窗口的文檔。因此,應(yīng)用可擁有如下形式:

Single-window utility app單一窗口實(shí)用程序應(yīng)用Single-window library-style app單一窗口庫(kù)類(lèi)型應(yīng)用Multiwindow document-based app多窗口基于文檔應(yīng)用

You should choose a basic app style early in your design process because that choice affects everything you do later. The single-window styles are preferred in many cases, especially for developers bringing apps from iOS. The single-window style typically yields a more streamlined user experience, and it also makes it easier for your app to support a full-screen mode. However, if your app works extensively with complex documents, the multiwindow style may be preferable because it provides more document-related infrastructure to help you implement your app.

在設(shè)計(jì)進(jìn)程的前期,就需要選定基本的應(yīng)用風(fēng)格,因?yàn)檫@個(gè)選擇將影響后續(xù)的所有事情。許多情況下推薦單一窗口應(yīng)用,尤其是開(kāi)發(fā)者從iOS移植過(guò)來(lái)的應(yīng)用。單一窗口應(yīng)用會(huì)提供更便捷的用戶(hù)體驗(yàn),同時(shí)也使應(yīng)用更易支持全屏模式。如果你的應(yīng)用需要大量處理復(fù)雜文檔,則更推薦多窗口應(yīng)用,因?yàn)樗峁┝烁辔募嚓P(guān)的基礎(chǔ)設(shè)施,以便實(shí)現(xiàn)應(yīng)用。

The Calculator app provided with OS X, shown in Figure 2-1, is an example of a single-window utility app. Utility apps typically handle ephemeral data or manage system processes. Calculator does not create or deal with any documents or persistent user data but simply processes numerical data entered by the user into the text field in its single window, displaying the results of its calculations in the same field. When the user quits the app, the data it processed is simply discarded.

OS X提供的計(jì)算機(jī)應(yīng)用,如圖2-1所示,是一個(gè)單一窗口實(shí)用程序應(yīng)用的例子。實(shí)用程序通常處理短暫的數(shù)據(jù)或管理系統(tǒng)進(jìn)程。計(jì)算器不創(chuàng)建或處理文檔,也不存儲(chǔ)用戶(hù)數(shù)據(jù),它只是在其窗口中簡(jiǎn)單地處理用戶(hù)輸入到文本框中的數(shù)據(jù),并展示計(jì)算結(jié)果。當(dāng)用戶(hù)退出這個(gè)應(yīng)用時(shí),數(shù)據(jù)會(huì)被簡(jiǎn)單地丟棄。

Figure 2-1  The Calculator single-window utility app

圖2-1 計(jì)算器,單一窗口實(shí)用程序

Single-window, library-style (or “shoebox”) apps do handle persistent user data. One of the most prominent examples of a library-style app is iPhoto, shown in Figure 2-2. The user data handled by iPhoto are photos (and associated metadata), which the app edits, displays, and stores. All user interaction with iPhoto happens in a single window. Although iPhoto stores its data in files, it doesn’t present the files to the user. The app presents a simplified interface so that users don’t need to manage files in order to use the app. Instead, they work directly with their photos. Moreover, iPhoto hides its files from regular manipulation in the Finder by placing them within a single package. In addition, the app saves the user’s editing changes to disk at appropriate times. So, users are relieved of the need to manually save, open, or close documents. This simplicity for users is one of the key advantages of the library-style app design.

單一窗口、庫(kù)類(lèi)型(或“鞋盒”)應(yīng)用處理可持久用戶(hù)數(shù)據(jù)。庫(kù)類(lèi)型應(yīng)用的一個(gè)最顯著的例子是iPhoto,如圖2-2所示。iPhoto處理的數(shù)據(jù)是照片(以及關(guān)聯(lián)的元數(shù)據(jù)),應(yīng)用可以編輯、顯示和存儲(chǔ)它們。用戶(hù)與iPhoto的所有交互都在單一窗口中進(jìn)行。盡管iPhoto將數(shù)據(jù)存儲(chǔ)到文件中,但它并不向用戶(hù)展示文件。應(yīng)用展示了一個(gè)簡(jiǎn)易的界面,用戶(hù)無(wú)需管理文件就可以使用應(yīng)用。相反,他們直接與照片打交道。iPhoto將其文件從Finder常規(guī)操作中隱藏,將它們放置到一個(gè)單獨(dú)的包中。另外,應(yīng)用在恰當(dāng)?shù)臅r(shí)間保存用戶(hù)的編輯。這樣,用戶(hù)從手動(dòng)保存、打開(kāi)或關(guān)閉文檔中解脫出來(lái)。簡(jiǎn)化用戶(hù)操作是庫(kù)類(lèi)型應(yīng)用設(shè)計(jì)的一個(gè)關(guān)鍵優(yōu)勢(shì)。

Figure 2-2  The iPhoto single-window app

圖2-2 iPhoto,單一窗口應(yīng)用

A good example of a multiwindow document-based app is TextEdit, which creates, displays, and edits documents containing plain or styled text and images. TextEdit does not organize or manage its documents—users do that with the Finder. Each TextEdit document opens in its own window, multiple documents can be open at one time, and the user interacts with the frontmost document using controls in the window’s toolbar and the app’s menu bar. Figure 2-3 shows a document created by TextEdit. For more information about the document-based app design, see Document-Based Apps Are Based on an NSDocument Subclass.

文本編輯是基于文檔的多窗口應(yīng)用的一個(gè)很好的例子,它創(chuàng)建、顯示、編輯包含簡(jiǎn)易或格式化文本和圖片的文檔。文本編輯不組織或管理文檔——用戶(hù)使用Finder來(lái)組織和管理它們。每個(gè)文本編輯的文檔在其自己的窗口中打開(kāi),許多文檔可同時(shí)打開(kāi),用戶(hù)使用窗口的工具欄、應(yīng)用的菜單欄與最上方的文檔進(jìn)行交互。圖2-3展示了一個(gè)由文本編輯創(chuàng)建的文檔。關(guān)于基于文檔的應(yīng)用設(shè)計(jì)的更多信息,參考Document-Based Apps Are Based on an NSDocument Subclass。

Figure 2-3  TextEdit document window

圖2-3 文本編輯文檔窗口

Both single-window and multiwindow apps can present an effective full-screen mode, which provides an immersive experience that enables users to focus on their tasks without distractions. For information about full-screen mode, seeImplementing the Full-Screen Experience.

單一窗口和多窗口應(yīng)用都可以呈現(xiàn)有效的全屏模式,全屏模式可以提供沉浸式體驗(yàn),確保用戶(hù)專(zhuān)注于它們的任務(wù)而不被打擾。關(guān)于全屏模式的更多信息,參考Implementing the Full-Screen Experience。

The Core Objects for All Cocoa Apps

通用核心對(duì)象

Regardless of whether you are using a single-window or multiwindow app style, all apps use the same core set of objects. Cocoa provides the default behavior for most of these objects. You are expected to provide a certain amount of customization of these objects to implement your app’s custom behavior.

不管使用單一窗口風(fēng)格,還是使用多窗口風(fēng)格,所有應(yīng)用都使用同一套核心對(duì)象。Cocoa為大多數(shù)對(duì)象提供了默認(rèn)行為。你應(yīng)當(dāng)對(duì)這些對(duì)象進(jìn)行適當(dāng)?shù)亩ㄖ疲瑏?lái)實(shí)現(xiàn)應(yīng)用的自定義行為。

Figure 2-4 shows the relationships among the core objects for the single-window app styles. The objects in this figure are separated according to whether they are part of themodel, view, or controller portions of the app. As you can see from the figure, the Cocoa–provided objects provide much of the controller and view layer for your app.

圖2-4展示了單一窗口應(yīng)用核心對(duì)象之間的關(guān)系。圖中的對(duì)象按照它是否為應(yīng)用模型、視圖或控制器的組成部分來(lái)劃分。從圖中可以看出,Cocoa提供的對(duì)象為應(yīng)用提供了大部分的控制器和視圖層。

Figure 2-4  Key objects in a single-window app

圖2-4 單一窗口應(yīng)用中的關(guān)鍵對(duì)象

Table 2-2 describes the roles played by the objects in the diagram.

表2-2描述了這些對(duì)象所扮演的角色

Table 2-2  The core objects used by all Cocoa apps

表2-2 通用核心對(duì)象

Object

Description

NSApplication object

NSApplication對(duì)象

(Required) Runs the event loop and manage interactions between your app and the system. You typically use theNSApplication class as is, putting any custom app-object-related code in your application delegate object.

(必須)運(yùn)行事件循環(huán),管理應(yīng)用與系統(tǒng)的交互。通常使用NSApplication類(lèi),把應(yīng)用對(duì)象相關(guān)的自定義代碼放置到應(yīng)用代理對(duì)象中。

Application delegate object

應(yīng)用代理對(duì)象

(Expected) A custom object that you provide which works closely with theNSApplication object to run the app and manage the transitions between different application states.

(期望)你提供的一個(gè)自定義對(duì)象,與NSApplication對(duì)象協(xié)同工作來(lái)運(yùn)行應(yīng)用、管理應(yīng)用不同狀態(tài)之間的轉(zhuǎn)換。

Your application delegate object must conform to the NSApplicationDelegate Protocol.

應(yīng)用代理對(duì)象必須遵守 NSApplicationDelegate Protocol。

Data model objects

數(shù)據(jù)模型對(duì)象

Store content specific to your app. A banking app might store a database containing financial transactions, whereas a painting app might store an image object or the sequence of drawing commands that led to the creation of that image.

存儲(chǔ)應(yīng)用內(nèi)容。銀行應(yīng)用可能會(huì)存儲(chǔ)一個(gè)包含財(cái)務(wù)交易的數(shù)據(jù)庫(kù),繪圖應(yīng)用可能存儲(chǔ)一個(gè)圖片對(duì)象,或是能生成圖片的繪圖命令序列。

Window controllers

窗口控制器

Responsible for loading and managing a single window each and coordinating with the system to handle standard window behaviors.

負(fù)責(zé)加載和管理單個(gè)窗口,并與系統(tǒng)協(xié)調(diào),處理基本窗口行為。

You subclass NSWindowController to manage both the window and its contents. Each window controller is responsible for everything that happens in its window. If the contents of your window are simple, the window controller may do all of the management itself. If your window is more complex, the window controller might use one or more view controllers to manage portions of the window.

需要繼承NSWindowController類(lèi)來(lái)管理窗口和其內(nèi)容。窗口控制器負(fù)責(zé)其窗口中發(fā)生的一切事務(wù)。如果窗口足夠簡(jiǎn)單,窗口控制器可能能夠自己完成所有的管理工作。如果窗口比較復(fù)雜,窗口控制器可能要使用一個(gè)或多個(gè)視圖控制器來(lái)管理窗口的各個(gè)部分。

Window objects

窗口對(duì)象

Represent your onscreen windows, configured in different styles depending on your app’s needs. For example, most windows have title bars and borders but you can also configure windows without those visual adornments. A window object is almost always managed by a window controller.

代表屏幕上的窗口,根據(jù)應(yīng)用需要進(jìn)行不同方式的配置。比如,大多數(shù)的窗口擁有標(biāo)題欄和邊框,但也可配置為不要這些可視化的裝飾。窗口對(duì)象幾乎總是由窗口控制器來(lái)管理。

An app can also have secondary windows, also known as dialogs and panels. These windows are subordinate to the current document window or, in the case of single-window apps, to the main window. They support the document or main window, for example, allowing selection of fonts and color, allowing the selection of tools from a palette, or displaying a warning? A secondary window is often modal.

應(yīng)用也可擁有二級(jí)窗口,通常被稱(chēng)為對(duì)話(huà)框和面板。這些窗口從屬于當(dāng)前文檔窗口;如果是單一窗口應(yīng)用,則從屬于主窗口。它們支持文檔或主窗口,允許選擇字體和顏色、從調(diào)色板中選擇工具或顯示一個(gè)警告。二級(jí)窗口通常是模態(tài)的。

View controllers

視圖控制器

Coordinate the loading of a single view hierarchy into your app. Use view controllers to divide up the work for managing more sophisticated window layouts. Your view controllers work together (with the window controller) to present the window contents.

負(fù)責(zé)協(xié)調(diào)向應(yīng)用中加載單一視圖層級(jí)。使用視圖控制器將復(fù)雜的窗口布局管理工作進(jìn)行分割。視圖控制器(與窗口控制器)協(xié)同工作,來(lái)呈現(xiàn)窗口內(nèi)容。

If you have developed iOS apps, be aware that AppKit view controllers play a less prominent role than UIKit view controllers. In OS X, AppKit view controllers are assistants to the window controller, which is ultimately responsible for everything that goes in the window. The main job of an AppKit view controller is to load its view hierarchy. Everything else is custom code that you write.

如果你曾經(jīng)開(kāi)發(fā)過(guò)iOS應(yīng)用,會(huì)發(fā)現(xiàn)AppKit視圖控制器沒(méi)有UIKit視圖控制器那么重要。在OS X中,AppKit視圖控制器是窗口控制器的輔助,它從根本上負(fù)責(zé)窗口中的所有事務(wù)。AppKit視圖控制器的主要任務(wù)是加載其視圖層次。剩余的事情就是你所寫(xiě)的自定義代碼。

View objects

視圖對(duì)象

Define a rectangular region in a window, draw the contents of that region, and handle events in that region. Views can be layered on top of each other to create view hierarchies, whereby one view obscures a portion of the underlying view.

在窗口中定義一個(gè)矩形區(qū)域,并在該區(qū)域中繪制內(nèi)容、處理事件。視圖可被放置在其它視圖之上來(lái)創(chuàng)建視圖層級(jí),借此一個(gè)視圖會(huì)遮蓋其下層視圖的一部分。

Control objects

控件對(duì)象

Represent standard system controls. These view subclasses provide standard visual items such as buttons, text fields, and tables that you can use to build your user interface. Although a few controls are used as is to present visual adornments, most work with your code is to manage user interactions with your app’s content.

代表基礎(chǔ)系統(tǒng)控件。這些視圖子類(lèi)提供了標(biāo)準(zhǔn)的可視化項(xiàng)目,如按鈕、文本框和表格,可使用它們來(lái)構(gòu)建用戶(hù)界面。盡管少數(shù)控件用于呈現(xiàn)可視化裝飾,但大多數(shù)控件的工作是與代碼協(xié)同工作,管理用戶(hù)與應(yīng)用內(nèi)容的交互。

Additional Core Objects for Multiwindow Apps

多窗口應(yīng)用附加的核心對(duì)象

As opposed to a single-window app, a multiwindow app uses several windows to present its primary content. The Cocoa support for multiwindow apps is built around a document-based model implemented by a subsystem called thedocument architecture. In this model, each document object manages its content, coordinates the reading and writing of that content from disk, and presents the content in a window for editing. All document objects work with the Cocoa infrastructure to coordinate event delivery and such, but each document object is otherwise independent of its fellow document objects.

與單一窗口應(yīng)用不同,多窗口應(yīng)用使用幾個(gè)窗口來(lái)展示其主要內(nèi)容。Cocoa對(duì)多窗口應(yīng)用的支持是圍繞基于文檔的模型來(lái)構(gòu)建的,這個(gè)模型由稱(chēng)作“文檔架構(gòu)”的子系統(tǒng)來(lái)實(shí)現(xiàn)。在這個(gè)模型中,每個(gè)文檔對(duì)象管理其內(nèi)容、協(xié)調(diào)磁盤(pán)的讀寫(xiě),并將內(nèi)容展示在窗口中以供編輯。所有的文檔對(duì)象與Cocoa基礎(chǔ)設(shè)施一同工作來(lái)協(xié)調(diào)事件的傳遞,但每個(gè)文檔對(duì)象與其它文檔對(duì)象都是獨(dú)立的。

Figure 2-5 shows the relationships among the core objects of a multiwindow document-based app. Many of the same objects in this figure are identical to those used by a single-window app. The main difference is the insertion of theNSDocumentController and NSDocument objects between the application objects and the objects for managing the user interface.

圖2-5展示了基于文檔的多窗口應(yīng)用的核心對(duì)象之間的關(guān)系。表格中的許多對(duì)象與單一窗口中使用的對(duì)象完全相同。主要的區(qū)別是在應(yīng)用程序?qū)ο笾g插入了NSDocumentController和NSDocument對(duì)象,以及管理用戶(hù)界面的對(duì)象。

Figure 2-5  Key objects in a multiwindow document app

表2-5 多窗口文檔應(yīng)用關(guān)鍵對(duì)象

Table 2-3 describes the role of the insertedNSDocumentController and NSDocument objects. (For information about the roles of the other objects in the diagram, seeTable 2-2.)

表2-3描述了插入的NSDocumentController和NSDocument對(duì)象的作用。(關(guān)于其它對(duì)象的作用信息,見(jiàn)表2-2)

Table 2-3  Additional objects used by multiwindow document apps

表2-3 多窗口文檔應(yīng)用使用的附加對(duì)象

Object

Description

Document Controller object

The NSDocumentController class defines a high-level controller for creating and managing all document objects. In addition to managing documents, the document controller also manages many document-related menu items, such as the Open Recent menu and the open and save panels.

NSDocumentController類(lèi)定義了一個(gè)高層的控制器,用于創(chuàng)建和管理所有的文檔對(duì)象。除管理文檔外,文檔控制器還管理許多文檔相關(guān)的菜單項(xiàng)目,比如“最近打開(kāi)”菜單、打開(kāi)和保存面板。

Document object

The NSDocument class is the base class for implementing documents in a multiwindow app. This class acts as the controller for the data objects associated with the document. You define your own custom subclasses to manage the interactions with your app’s data objects and to work with one or more NSWindowController objects to display the document contents on the screen.

NSDocument類(lèi)是多窗口應(yīng)用實(shí)現(xiàn)文檔的基礎(chǔ)類(lèi)。這個(gè)類(lèi)扮演著與文檔相關(guān)的數(shù)據(jù)對(duì)象的控制器。可自定義其子類(lèi),來(lái)管理與應(yīng)用數(shù)據(jù)對(duì)象的交互,并與一個(gè)或多個(gè)NSWindowController對(duì)象協(xié)同工作,在屏幕上顯示文檔內(nèi)容。

Integrating iCloud Support Into Your App

向應(yīng)用中集成iCloud

No matter how you store your app’s data, iCloud is a convenient way to make that data available to all of a user’s devices. To integrate iCloud into your app, you change where you store user files. Instead of storing them in the user’s Home folder or in your App Sandbox container, you store them in special file system locations known as ubiquity containers. A ubiquity container serves as the local representation of corresponding iCloud storage. It is outside of your App Sandbox container, and so requires specific entitlements for your app to interact with it.

不管如何存儲(chǔ)應(yīng)用數(shù)據(jù),iCloud是使數(shù)據(jù)向用戶(hù)的所有設(shè)備可見(jiàn)的一個(gè)便捷方法。將iCloud集成到應(yīng)用中,要改變存儲(chǔ)用戶(hù)文件的位置。將以往把它們存儲(chǔ)到應(yīng)用沙箱容器中的用戶(hù)主文件夾中,替換為存儲(chǔ)到的特殊文件系統(tǒng)位置——這個(gè)位置被稱(chēng)為無(wú)處不在的容器。無(wú)處不在的容器充當(dāng)相應(yīng)iCloud存儲(chǔ)的本地表示。它在應(yīng)用沙箱之外,所以需要特殊的應(yīng)用授權(quán)來(lái)與其交互。

In addition to a change in file system locations, your app design needs to acknowledge that your data model is accessible to multiple processes. The following considerations apply:

除了文件系統(tǒng)位置之外的變化,應(yīng)用設(shè)計(jì)需要確保數(shù)據(jù)模型可供多進(jìn)程來(lái)存取。考慮以下情況:

Document-based apps get iCloud support through the NSDocument class, which handles most of the interactions required to manage the on-disk file packages that represent documents.基于文件的應(yīng)用通過(guò)NSDocument類(lèi)來(lái)獲取iCloud支持。NSDocument類(lèi)處理大多數(shù)交互,這些交互是管理表示文檔的磁盤(pán)包文件所必須的。If you implement a custom data model and manage files yourself, you must explicitly use file coordination to ensure that the changes you make are done safely and in concert with the changes made on the user’s other devices. For details, seeThe Role of File Coordinators and Presenters in File System Programming Guide.如果實(shí)現(xiàn)了自定義數(shù)據(jù)模型并自己管理文件,則必須明確使用文件協(xié)調(diào),來(lái)確保你產(chǎn)生的變化是安全進(jìn)行地,并與其它設(shè)備上產(chǎn)生的變化保持一致。更多細(xì)節(jié),參考File System Programming Guide中的The Role of File Coordinators and Presenters。For storing small amounts of data in iCloud, you use key-value storage. Use key-value storage for such things as stocks or weather information, locations, bookmarks, a recent-documents list, settings and preferences, and simple game state. Every iCloud app should take advantage of key-value storage. To interact with key-value storage, you use the sharedNSUbiquitousKeyValueStore object.在iCloud中存儲(chǔ)少量數(shù)據(jù),可使用鍵-值存儲(chǔ)。鍵-值存儲(chǔ)用于股票或天氣信息、位置、書(shū)簽、最近文檔列表、設(shè)置和偏好、簡(jiǎn)單游戲狀態(tài)等。每個(gè)iCloud應(yīng)用都應(yīng)利用鍵-值存儲(chǔ)。與鍵-值存儲(chǔ)交互,使用共享的NSUbiquitousKeyValueStore對(duì)象。

To learn how to adopt iCloud in your app, read iCloud Design Guide.

學(xué)習(xí)如何在應(yīng)用中適配iCloud,閱讀iCloud Design Guide.

Shoebox-Style Apps Should Not Use NSDocument

“鞋盒”風(fēng)格的應(yīng)用不應(yīng)當(dāng)使用NSDocument

When implementing a single-window, shoebox-style (sometimes referred to as a “l(fā)ibrary” style) app, it is sometimes better not to useNSDocument objects to manage your content. TheNSDocument class was designed specifically for use in multiwindow document apps. Instead, use custom controller objects to manage your data. Those custom controllers would then work with a view controller or your app’s main window controller to coordinate the presentation of the data.

實(shí)現(xiàn)單一窗口、“鞋盒”風(fēng)格(有時(shí)指“庫(kù)”類(lèi)型)的應(yīng)用時(shí),有些時(shí)候不使用NSDocument對(duì)象用來(lái)管理內(nèi)容為好。NSDocument類(lèi)是專(zhuān)門(mén)針對(duì)多窗口文檔應(yīng)用來(lái)設(shè)計(jì)的。作為替代,使用自定義的控制器對(duì)象來(lái)管理數(shù)據(jù)。這些自定義控制器與視圖控制器或應(yīng)用主窗口控制器來(lái)協(xié)同展示數(shù)據(jù)。

Although you normally use an NSDocumentController object only in multiwindow apps, you can subclass it and use it in a single-window app to coordinate the Open Recent and similar behaviors. When subclassing, though, you must override any methods related to the creation of NSDocument objects.

盡管通常只在多窗口應(yīng)用中使用NSDocumentController對(duì)象,但你可以繼承它并用在單一窗口應(yīng)用中,來(lái)協(xié)調(diào)“最近打開(kāi)”及類(lèi)似行為。不過(guò),在繼承這個(gè)類(lèi)時(shí),應(yīng)當(dāng)重寫(xiě)與創(chuàng)建NSDocument對(duì)象相關(guān)的所有方法。

Document-Based Apps Are Based on an NSDocument Subclass

基于文檔的應(yīng)用以NSDocument的子類(lèi)為基礎(chǔ)

Documents are containers for user data that can be stored in files and iCloud. In a document-based design, the app enables users to create and manage documents containing their data. One app typically handles multiple documents, each in its own window, and often displays more than one document at a time. For example, a Word processor provides commands to create new documents, it presents an editing environment in which the user enters text and embeds graphics into the document, it saves the document data to disk (and, optionally, iCloud), and it provides other document-related commands, such as printing and version management. In Cocoa, the document-based app design is enabled by the document architecture, which is part of of the AppKit framework.

文檔是用戶(hù)數(shù)據(jù)的容器,可存儲(chǔ)到文件和iCloud中。在基于文檔的設(shè)計(jì)中,應(yīng)用允許用戶(hù)創(chuàng)建和管理包含他們的數(shù)據(jù)的文檔。一個(gè)應(yīng)用通常處理多個(gè)文檔,每個(gè)文檔在其自身的窗口中,并且應(yīng)用經(jīng)常同時(shí)顯示多個(gè)文檔。例如,一個(gè)文檔處理器提供創(chuàng)建新文檔的命令,它提供一個(gè)編輯環(huán)境,用戶(hù)在其中輸入文本、嵌入圖片;它將文檔數(shù)據(jù)存儲(chǔ)到磁盤(pán)(也可以存儲(chǔ)到iCloud);它提供其它文件相關(guān)的命令,比如打印和版本管理。在Cocoa中,基于文檔的應(yīng)用設(shè)計(jì)被文檔架構(gòu)所允許,這個(gè)文檔架構(gòu)是AppKit框架的一部分。

Documents in OS X

OS X中的文檔

There are several ways to think of a document. Conceptually, a document is a container for a body of information that can be named and stored in a disk file and in iCloud. In this sense, the document is not the same as the file but is an object in memory that owns and manages the document data. To users, the document is their information—such as text and graphics formatted on a page. Programmatically, a document is an instance of a customNSDocument subclass that knows how to represent internally persistent data that it can display in windows. This document object knows how to read document data from a file and create an object graph in memory for the document data model. It also knows how to handle the user’s editing commands to modify the data model and write the document data back out to disk. So, the document object mediates between different representations of document data, as shown in Figure 2-6.

有多個(gè)角度來(lái)看待一個(gè)文檔。從概念上說(shuō),一個(gè)文檔是信息的一個(gè)容器,可被命名,可存儲(chǔ)到磁盤(pán)文件或iCloud中。這種情況下,文檔與文件不同,它是一個(gè)內(nèi)存中的對(duì)象,擁有并管理文檔數(shù)據(jù)。對(duì)用戶(hù)來(lái)說(shuō),文檔是他們的信息——比如頁(yè)面上格式化的文本和圖片。從編程上說(shuō),一個(gè)文檔是自定義NSDocument子類(lèi)的一個(gè)實(shí)例,它知道如何表示內(nèi)部的持久化數(shù)據(jù),也能夠?qū)⑦@些數(shù)據(jù)顯示在窗口中。文檔對(duì)象知道如何從文件讀取文檔數(shù)據(jù)、如何在內(nèi)存中為文檔數(shù)據(jù)模型創(chuàng)建圖形。它還知道如何處理用戶(hù)的編輯命令,并據(jù)此來(lái)修改數(shù)據(jù)模型,并把文檔數(shù)據(jù)回寫(xiě)到磁盤(pán)。所以,文檔對(duì)象在文檔數(shù)據(jù)的不同表示中起到中介的作用,如圖2-6所示。

Figure 2-6  Document file, object, and data model

表2-6 文檔文件、對(duì)象和數(shù)據(jù)模型

Using iCloud, documents can be shared automatically among a user’s computers and iOS devices. Changes to the document data are synchronized without user intervention. For information about iCloud, seeIntegrating iCloud Support Into Your App.

使用iCloud,文檔可自動(dòng)在用戶(hù)計(jì)算機(jī)和iOS設(shè)備之間分享。文檔數(shù)據(jù)變化可自動(dòng)同步,無(wú)需用戶(hù)介入。關(guān)于iCloud的信息,參考Integrating iCloud Support Into Your App。

The Document Architecture Provides Many Capabilities for Free

文檔架構(gòu)免費(fèi)提供多種能力

The document-based style of app is a design choice that you should consider when you design your app. If it makes sense for your users to create multiple discrete sets of data, each of which they can edit in a graphical environment and store in files or iCloud, then you certainly should plan to develop a document-based app.

當(dāng)你設(shè)計(jì)應(yīng)用時(shí),需要考慮這個(gè)選擇——應(yīng)用是否采用基于文檔的形式。如果用戶(hù)需要?jiǎng)?chuàng)建多個(gè)獨(dú)立成套的數(shù)據(jù),每份數(shù)據(jù)都可在圖形環(huán)境下編輯、并保存到文檔或iCloud中,那么就應(yīng)當(dāng)計(jì)劃去開(kāi)發(fā)一個(gè)基于文檔的應(yīng)用。

The Cocoa document architecture provides a framework for document-based apps to do the following things:

Cocoa文檔架構(gòu)為基于文檔的應(yīng)用提供了一個(gè)框架,可完成下列任務(wù):

Create new documents. The first time the user chooses to save a new document, it presents a dialog enabling the user to name and save the document in a disk file in a user-chosen location.創(chuàng)建新文檔。用戶(hù)首次選擇保存新文檔時(shí),它展示一個(gè)對(duì)話(huà)框,允許用戶(hù)來(lái)命名、在用戶(hù)選擇的位置將文檔存儲(chǔ)到磁盤(pán)文件中。Open existing documents stored in files. A document-based app specifies the types of document it can read and write, as well as read-only and write-only types. It can represent the data of different types internally and display the data appropriately. It can also close documents.打開(kāi)存儲(chǔ)在文件中的現(xiàn)有文檔。一個(gè)基于文檔的應(yīng)用指定它能夠讀取和寫(xiě)入的文檔類(lèi)型,以及只讀和只寫(xiě)的文檔類(lèi)型。它能夠表示不同類(lèi)型的數(shù)據(jù),并將它們恰當(dāng)?shù)仫@示出來(lái)。它還能關(guān)閉文檔。Automatically save documents. Document-based apps can adopt autosaving in place, and its documents are automatically saved at appropriate times so that the data the user sees on screen is effectively the same as that saved on disk. Saving is done safely, so that an interrupted save operation does not leave data inconsistent.自動(dòng)保存文檔。基于文檔的應(yīng)用采用自動(dòng)保存,它的文檔會(huì)在適當(dāng)?shù)臅r(shí)候自動(dòng)保存,以保證用戶(hù)在屏幕上看到的數(shù)據(jù)與存儲(chǔ)在磁盤(pán)上的數(shù)據(jù)完全一致。保存過(guò)程是安全的,所以一個(gè)被打斷的保存操作不會(huì)留下不一致的數(shù)據(jù)。Asynchronously read and write document data. Reading and writing are done asynchronously on a background thread, so that lengthy operations do not make the app’s user interface unresponsive. In addition, reads and writes are coordinated using NSFilePresenter protocol andNSFileCoordinator class to reduce version conflicts. Coordinated reads and writes reduce version conflicts both among different apps sharing document data in local storage and among different instances of an app on different devices sharing document data via iCloud.異步讀取和寫(xiě)入文檔數(shù)據(jù)。讀取過(guò)程和寫(xiě)入過(guò)程是在后臺(tái)線(xiàn)程上異步完成的,所以長(zhǎng)時(shí)間的操作不會(huì)導(dǎo)致用戶(hù)界面卡頓。另外,讀取和寫(xiě)入使用NSFilePresenter協(xié)議和NSFileCoordinator類(lèi)來(lái)協(xié)調(diào),以減少版本沖突。經(jīng)過(guò)協(xié)調(diào)的讀取和寫(xiě)入可減少版本沖突,既對(duì)在本地存儲(chǔ)中共享文檔數(shù)據(jù)的不同應(yīng)用有效,也對(duì)通過(guò)iCloud共享文檔的同一應(yīng)用在不同設(shè)備上的不同實(shí)例有效。Manage multiple versions of documents. Autosave creates versions at regular intervals, and users can manually save a version whenever they wish. Users can browse versions and revert the document’s contents to a chosen version using a Time Machine–like interface. The version browser is also used to resolve version conflicts from simultaneous iCloud updates.管理文檔的不同版本。自動(dòng)保存定期創(chuàng)建新版本,用戶(hù)也可根據(jù)意愿手動(dòng)保存新版本。使用一個(gè)類(lèi)似Time Machine的界面,用戶(hù)可以瀏覽版本,并將文檔內(nèi)容轉(zhuǎn)換到所選擇的版本。版本瀏覽器也用于解決iCloud同時(shí)更新時(shí)產(chǎn)生的沖突。Print documents. The print dialog and page setup dialog enable the user to choose various page layouts.打印文檔。打印對(duì)話(huà)框和頁(yè)面設(shè)置對(duì)話(huà)框允許用戶(hù)選擇多種頁(yè)面布局。Monitor and set the document’s edited status and validate menu items. To avoid automatic saving of inadvertent changes, old files are locked from editing until explicitly unlocked by the user.監(jiān)控和設(shè)置文檔的編輯狀態(tài)、驗(yàn)證菜單項(xiàng)目。為避免自動(dòng)保存無(wú)意的更改,舊文件被鎖定而禁止編輯,除非用戶(hù)明確地將其解鎖。Track changes. The document manages its edited status and implements multilevel undo and redo.追蹤變動(dòng)。文檔管理它自身的編輯狀態(tài),實(shí)現(xiàn)多層撤銷(xiāo)和重做操作。Handle app and window delegation. Notifications are sent and delegate methods called at significant lifecycle events, such as when the app terminates.處理應(yīng)用和窗口代理。在生命周期的顯著事件發(fā)生時(shí),會(huì)發(fā)送通知、調(diào)用代理方法,比如當(dāng)應(yīng)用結(jié)束時(shí)。

See Document-Based App Programming Guide for Mac for more detailed information about how to implement a document-based app.

參閱Document-Based App Programming Guide for Mac來(lái)獲取實(shí)現(xiàn)基于文檔應(yīng)用的詳細(xì)信息。

The App Life Cycle

應(yīng)用生命周期

The app life cycle is the progress of an app from its launch through its termination. Apps can be launched by the user or the system. The user launches apps by double-clicking the app icon, using Launchpad, or opening a file whose type is currently associated with the app. In OS X v10.7 and later, the system launches apps at user login time when it needs to restore the user’s desktop to its previous state.

應(yīng)用的生命周期是一個(gè)應(yīng)用從加載到終結(jié)的過(guò)程。應(yīng)用可由用戶(hù)或系統(tǒng)來(lái)加載。用戶(hù)使用Launchpad,通過(guò)雙擊應(yīng)用圖標(biāo)來(lái)加載應(yīng)用,或打開(kāi)一個(gè)類(lèi)型與應(yīng)用關(guān)聯(lián)的文件。在OS X v10.7及之后,當(dāng)系統(tǒng)需要恢復(fù)用戶(hù)桌面到其之前狀態(tài)時(shí),會(huì)在用戶(hù)登錄時(shí)加載應(yīng)用。

When an app is launched, the system creates a process and all of the normal system-related data structures for it. Inside the process, it creates a main thread and uses it to begin executing your app’s code. At that point, your app’s code takes over and your app is running.

當(dāng)一個(gè)應(yīng)用被加載時(shí),系統(tǒng)會(huì)為其創(chuàng)建一個(gè)進(jìn)程和系統(tǒng)相關(guān)的數(shù)據(jù)結(jié)構(gòu)。在進(jìn)程之內(nèi),會(huì)創(chuàng)建一個(gè)主線(xiàn)程,并使用這個(gè)主線(xiàn)程來(lái)開(kāi)始執(zhí)行應(yīng)用代碼。從這一刻起,應(yīng)用代碼接管,應(yīng)用開(kāi)始運(yùn)行。

The main Function is the App Entry Point

main函數(shù)是應(yīng)用的入口

Like any C-based app, the main entry point for a Mac app at launch time is themain function. In a Mac app, the main function is used only minimally. Its main job is to give control to the AppKit framework. Any new project you create in Xcode comes with a defaultmain function like the one shown in Listing 2-1. You should normally not need to change the implementation of this function.

與任何基于C語(yǔ)言的應(yīng)用類(lèi)似,Mac應(yīng)用加載時(shí)的主入口是main函數(shù)。在Mac應(yīng)用中,main函數(shù)被盡可能少地使用。它的主要工作是把控制權(quán)交給AppKit框架。你在Xcode中創(chuàng)建的任何新工程,都會(huì)有一個(gè)類(lèi)似列表2-1的默認(rèn)main函數(shù)。你通常無(wú)需更改這個(gè)函數(shù)的實(shí)現(xiàn)。

Listing 2-1  The main function of a Mac app

列表2-1 Mac應(yīng)用的main函數(shù)

#import <Cocoa/Cocoa.h>int main(int argc, char *argv[]){    return NSApplicationMain(argc,  (const char **) argv);}The NSApplicationMain function initializes your app and prepares it to run. As part of the initialization process, this function does several things:

NSApplicationMain函數(shù)初始化應(yīng)用,并為其運(yùn)行做準(zhǔn)備。作為初始化進(jìn)程的一部分,這個(gè)函數(shù)做幾件事情:

Creates an instance of the NSApplication class. You can access this object from anywhere in your app using thesharedApplication class method.創(chuàng)建NSApplication類(lèi)的一個(gè)實(shí)例。可使用sharedApplication類(lèi)方法,在應(yīng)用的任何地方訪問(wèn)這個(gè)對(duì)象。Loads the nib file specified by the NSMainNibFile key in theInfo.plist file and instantiates all of the objects in that file. This is your app’s main nib file and should contain your application delegate and any other critical objects that must be loaded early in the launch cycle. Any objects that are not needed at launch time should be placed in separate nib files and loaded later.加載Info.plist文件中NSMainNibFile鍵描述的nib文件,并實(shí)例化這個(gè)文件中的所有對(duì)象。這是應(yīng)用的主nib文件,應(yīng)當(dāng)包含在加載周期的早期必須加載的應(yīng)用程序代理和其它關(guān)鍵對(duì)象。加載期間非必須的其它對(duì)象,應(yīng)當(dāng)放置到單獨(dú)的nib文件中,稍后加載。Calls the run method of your application object to finish the launch cycle and begin processing events.調(diào)用應(yīng)用程序?qū)ο蟮膔un方法,結(jié)束加載周期,開(kāi)始處理事件。

By the time the run method is called, the main objects of your app are loaded into memory but the app is still not fully launched. Therun method notifies the application delegate that the app is about to launch, shows the application menu bar, opens any files that were passed to the app,does some framework housekeeping, and starts the event processing loop. All of this work occurs on the app’s main thread with one exception. Files may be opened in secondary threads if the canConcurrentlyReadDocumentsOfType: class method of the correspondingNSDocument object returns YES.

run方法調(diào)用之后,應(yīng)用的主要對(duì)象已經(jīng)加載到內(nèi)存,但應(yīng)用還沒(méi)有完全啟動(dòng)。run方法通知應(yīng)用代理應(yīng)用即將啟動(dòng)、顯示應(yīng)用目錄欄、打開(kāi)傳遞到應(yīng)用的任何文件、進(jìn)行框架清理、開(kāi)始事件處理循環(huán)。所有這些工作都在主線(xiàn)程上發(fā)生,只有一個(gè)例外——如果相應(yīng)的NSDocument對(duì)象的canConcurrentlyReadDocumentsOfType:類(lèi)方法返回YES,文件或許會(huì)在二級(jí)線(xiàn)程上打開(kāi)。

If your app preserves its user interface between launch cycles, Cocoa loads any preserved data at launch time and uses it to re-create the windows that were open the last time your app was running. For more information about how to preserve your app’s user interface, see User Interface Preservation.

如果應(yīng)用在啟動(dòng)周期保存了其用戶(hù)界面,Cocoa會(huì)在啟動(dòng)時(shí)加載保存的數(shù)據(jù),并使用它來(lái)重新創(chuàng)建應(yīng)用最近一次運(yùn)行時(shí)打開(kāi)的窗口。關(guān)于如何保存應(yīng)用用戶(hù)界面的更多信息,參考User Interface Preservation.

The App’s Main Event Loop Drives Interactions

應(yīng)用的主事件循環(huán)驅(qū)動(dòng)交互

As the user interacts with your app, the app’s main event loop processes incoming events and dispatches them to the appropriate objects for handling. When theNSApplication object is first created, it establishes a connection with the system window server, which receives events from the underlying hardware and transfers them to the app. The app also sets up a FIFO event queue to store the events sent to it by the window server. The main event loop is then responsible for dequeueing and processing events waiting in the queue, as shown in Figure 2-7.

當(dāng)用戶(hù)與應(yīng)用交互時(shí),應(yīng)用主事件循環(huán)處理進(jìn)來(lái)的事件,并將它們分配到適合的處理對(duì)象。當(dāng)NSApplication對(duì)象首次創(chuàng)建時(shí),它會(huì)與系統(tǒng)窗口服務(wù)器建立一個(gè)連接。系統(tǒng)窗口服務(wù)器會(huì)從底層硬件接收事件,并將它們傳遞給應(yīng)用。應(yīng)用也會(huì)建立一個(gè)先入先出的事件隊(duì)列,來(lái)存儲(chǔ)窗口服務(wù)器發(fā)送給它的事件。主事件循環(huán)負(fù)責(zé)取出并處理在隊(duì)列中等待的事件,如圖2-7所示。

Figure 2-7  The main event loop

圖2-7 主事件循環(huán)

The run method of the NSApplication object is the workhorse of the main event loop. In a closed loop, this method executes the following steps until the app terminates:

NSApplication對(duì)象的run方法是主事件循環(huán)的主要執(zhí)行者。在封閉循環(huán)中,這個(gè)方法執(zhí)行下列步驟,直至應(yīng)用終結(jié):

Services window-update notifications, which results in the redrawing of any windows that are marked as “dirty.”為應(yīng)用更新通知服務(wù),應(yīng)用更新通知會(huì)使標(biāo)記為“已變化”的窗口進(jìn)行重繪。Dequeues an event from its internal event queue using the nextEventMatchingMask:untilDate:inMode:dequeue: method and converts the event data into anNSEvent object.使用nextEventMatchingMask:untilDate:inMode:dequeue:方法從其事件隊(duì)列中取出一個(gè)事件,并將事件數(shù)據(jù)轉(zhuǎn)換成一個(gè)NSEvent對(duì)象。Dispatches the event to the appropriate target object using the sendEvent: method of NSApplication.使用NSApplication的方法將sendEvent:事件分派到合適的目標(biāo)對(duì)象。

When the app dispatches an event, the sendEvent: method uses the type of the event to determine the appropriate target. There are two major types of input events: key events and mouse events. Key events are sent to the key window—the window that is currently accepting key presses. Mouse events are dispatched to the window in which the event occurred.

當(dāng)應(yīng)用分派事件時(shí),sendEvent:方法使用事件類(lèi)型來(lái)決定適合的目標(biāo)。輸入事件有兩大類(lèi):鍵盤(pán)事件和鼠標(biāo)事件。鍵盤(pán)事件會(huì)發(fā)送給鍵盤(pán)窗口——即當(dāng)前接收鍵盤(pán)輸入的窗口。鼠標(biāo)事件會(huì)分派到事件發(fā)生的窗口。

For mouse events, the window looks for the view in which the event occurred and dispatches the event to that object first. Views areresponder objects and are capable of responding to any type of event. If the view is a control, it typically uses the event to generate anaction message for its associated target.

對(duì)于鼠標(biāo)事件,窗口會(huì)查找事件發(fā)生所在時(shí)所在的視圖,并首先將這個(gè)事件發(fā)送到那個(gè)視圖對(duì)象。視圖是響應(yīng)者對(duì)象,能夠響應(yīng)任何類(lèi)型的事件。如果視圖是一個(gè)控件,它通常使用事件,為與其關(guān)聯(lián)的目標(biāo)創(chuàng)建一個(gè)動(dòng)作信息。

The overall process for handling events is described in detail in Cocoa Event Handling Guide.

事件處理的整個(gè)過(guò)程,在Cocoa Event Handling Guide中有詳細(xì)描述。

Automatic and Sudden Termination of Apps Improve the User Experience

應(yīng)用的自動(dòng)結(jié)束和立即結(jié)束可增強(qiáng)用戶(hù)體驗(yàn)

In OS X v10.7 and later, the use of the Quit command to terminate an app is diminished in favor of more user-centric techniques. Specifically, Cocoa supports two techniques that make the termination of an app transparent and fast:

在OS X v10.7及其之后,為支持更加以用戶(hù)為中心的技術(shù),使用Quit命令來(lái)結(jié)束應(yīng)用的情況減少了。更確切的說(shuō),Cocoa支持兩種技術(shù),使用結(jié)束應(yīng)用更加透明和迅速:

Automatic termination eliminates the need for users to quit an app. Instead, the system manages app termination transparently behind the scenes, terminating apps that are not in use to reclaim needed resources such as memory.自動(dòng)結(jié)束排除了用戶(hù)退出應(yīng)用的需要。作為代替,系統(tǒng)在幕后管理應(yīng)用的結(jié)束——結(jié)束那些不使用的應(yīng)用以回收比如內(nèi)存之類(lèi)的資源。Sudden termination allows the system to kill an app’s process immediately without waiting for it to perform any final actions. The system uses this technique to improve the speed of operations such as logging out of, restarting, or shutting down the computer.立即結(jié)束允許系統(tǒng)立即結(jié)束一個(gè)應(yīng)用的進(jìn)程,而無(wú)需等待其進(jìn)行任何操作。系統(tǒng)使用這項(xiàng)技術(shù)來(lái)提升諸如退出登錄、重啟、關(guān)機(jī)等操作的速度。

Automatic termination and sudden termination are independent techniques, although both are designed to improve the user experience of app termination. Although Apple recommends that apps support both, an app can support one technique and not the other. Apps that support both techniques can be terminated by the system without the app being involved at all. On the other hand, if an app supports sudden termination but not automatic termination, then it must be sent a Quit event, which it needs to process without displaying any user interface dialogs.

自動(dòng)結(jié)束和立即結(jié)束是獨(dú)立的技術(shù),盡管它們都是被設(shè)計(jì)為增強(qiáng)應(yīng)用結(jié)束的用戶(hù)體驗(yàn)。盡管蘋(píng)果推薦應(yīng)用同時(shí)支持這兩種技術(shù),但應(yīng)用可以只支持一種,而不支持另外一種。同時(shí)支持這兩種技術(shù)的應(yīng)用可被系統(tǒng)結(jié)束而完全無(wú)需應(yīng)用參與。另一方面,如果應(yīng)用支持立即結(jié)束而不支持自動(dòng)結(jié)束,那么它必須被發(fā)送一個(gè)Quit事件,它需要這個(gè)事件來(lái)處理,而不顯示任何用戶(hù)界面對(duì)話(huà)框。

Automatic termination transfers the job of managing processes from the user to the system, which is better equipped to handle the job. Users do not need to manage processes manually anyway. All they really need is to run apps and have those apps available when they need them. Automatic termination makes that possible while ensuring that system performance is not adversely affected.

自動(dòng)結(jié)束把管理進(jìn)程的工作由用戶(hù)轉(zhuǎn)換給了系統(tǒng),而系統(tǒng)更善于處理這項(xiàng)工作。用戶(hù)不需要去手動(dòng)管理進(jìn)程。他們需要的僅是運(yùn)行應(yīng)用,當(dāng)需要它們的時(shí)候使它們可見(jiàn)。自動(dòng)結(jié)束使其可行,同時(shí)還保證了不會(huì)對(duì)系統(tǒng)表現(xiàn)產(chǎn)生不利影響。

Apps must opt in to both automatic termination and sudden termination and implement appropriate support for them. In both cases, the app must ensure that any user data is saved well before termination can happen. And because the user does not quit an autoterminable app, such an app should also save the state of its user interface using the built-in Cocoa support. Saving and restoring the interface state provides the user with a sense of continuity between app launches.

應(yīng)用必須在自動(dòng)結(jié)束和立即結(jié)束之間選擇其一,并為它們實(shí)現(xiàn)恰當(dāng)?shù)闹С帧T趦煞N情況下,應(yīng)用必須確保在結(jié)束發(fā)生之前,用戶(hù)數(shù)據(jù)已被妥善保存。而且由于用戶(hù)不會(huì)退出一個(gè)自動(dòng)結(jié)束的應(yīng)用,所以這樣的應(yīng)用也應(yīng)當(dāng)使用內(nèi)建的Cocoa支持來(lái)保存其用戶(hù)界面狀態(tài)。保存和恢復(fù)界面狀態(tài)為用戶(hù)提供連續(xù)的體驗(yàn)。

For information on how to support for automatic termination in your app, seeAutomatic Termination. For information on how to support sudden termination, seeSudden Termination.

關(guān)于如何支持自動(dòng)結(jié)束,參考Automatic Termination。關(guān)于如何支持立即結(jié)束,參考Sudden Termination。

Support the Key Runtime Behaviors in Your Apps

在應(yīng)用中支持關(guān)鍵的運(yùn)行時(shí)特性

No matter what style of app you are creating, there are specific behaviors that all apps should support. These behaviors are intended to help users focus on the content they are creating rather than focus on app management and other busy work that is not part of creating their content.

不管要?jiǎng)?chuàng)建何種形式的應(yīng)用,都有一些所有應(yīng)用都應(yīng)當(dāng)支持的特性。這些特性旨在幫助用戶(hù)專(zhuān)注于他們創(chuàng)建的內(nèi)容,而非應(yīng)用管理或其它與內(nèi)容無(wú)關(guān)的繁瑣工作。

Automatic Termination

自動(dòng)結(jié)束

Automatic termination is a feature that you must explicitly code for in your app. Declaring support for automatic termination is easy, but apps also need to work with the system to save the current state of their user interface so that it can be restored later as needed. The system can kill the underlying process for an auto-terminable app at any time, so saving this information maintains continuity for the app. Usually, the system kills an app’s underlying process some time after the user has closed all of the app’s windows. However, the system may also kill an app with open windows if the app is not currently on screen, perhaps because the user hid it or switched spaces.

自動(dòng)結(jié)束特性需要應(yīng)用進(jìn)行顯式地編程。聲明支持自動(dòng)結(jié)束很簡(jiǎn)單,但應(yīng)用需要與系統(tǒng)協(xié)同,保存用戶(hù)界面的當(dāng)前狀態(tài),以便以后根據(jù)需要來(lái)恢復(fù)。系統(tǒng)在任何時(shí)候都可以結(jié)束一個(gè)自動(dòng)結(jié)束應(yīng)用的底層進(jìn)程,所以需要保存這些信息來(lái)維護(hù)應(yīng)用的連續(xù)性。通常,當(dāng)用戶(hù)關(guān)閉了應(yīng)用的所有窗口一段時(shí)間之后,系統(tǒng)會(huì)結(jié)束應(yīng)用的底層進(jìn)程。然而,如果應(yīng)用不在當(dāng)前屏幕,可能是用戶(hù)隱藏了它或交換了空間,那么即使應(yīng)用有打開(kāi)的窗口,系統(tǒng)也可能會(huì)結(jié)束它。

To support automatic termination, you should do the following:

為支持自動(dòng)結(jié)束,應(yīng)做如下工作:

Declare your app’s support for automatic termination, either programmatically or using anInfo.plist key.聲明應(yīng)用支持自動(dòng)結(jié)束,采用編程方式或使用Info.plist一個(gè)的鍵。Support saving and restoring your window configurations.支持保存和恢復(fù)窗口配置。Save the user’s data at appropriate times.在適當(dāng)?shù)臅r(shí)候保存用戶(hù)數(shù)據(jù)。Single-window, library-style apps should implement strategies for saving data at appropriate checkpoints.單一窗口、庫(kù)類(lèi)型應(yīng)用應(yīng)當(dāng)實(shí)現(xiàn)在適當(dāng)檢查點(diǎn)保存數(shù)據(jù)的方法。Multiwindow, document-based apps can use the autosaving and saveless documents capabilities inNSDocument.多窗口、基于文檔的應(yīng)用可使用NSDocument中的自動(dòng)保存和不需保存文檔的功能。Whenever possible, support sudden termination for your app as well.可能的時(shí)候,讓你的應(yīng)用也支持立即結(jié)束。

Enabling Automatic Termination in Your App

在應(yīng)用中允許自動(dòng)結(jié)束

Declaring support for automatic termination lets the system know that it should manage the actual termination of your app at appropriate times. An app has two ways to declare its support for automatic termination:

聲明支持自動(dòng)結(jié)束會(huì)讓系統(tǒng)知道在適當(dāng)?shù)臅r(shí)刻管理實(shí)際的應(yīng)用結(jié)束。應(yīng)用有兩種方式來(lái)聲明支持自動(dòng)結(jié)束:

Include the NSSupportsAutomaticTermination key (with the valueYES) in the app’s Info.plist file. This sets the app’s default support status.在應(yīng)用的Info.plist文件中包含NSSupportsAutomaticTermination鍵(值設(shè)置為YES)。這樣設(shè)置了應(yīng)用默認(rèn)支持狀態(tài)。Use the NSProcessInfo class to declare support for automatic termination dynamically. Use this technique to change the default support of an app that includes theNSSupportsAutomaticTermination key in itsInfo.plist file.使用NSProcessInfo類(lèi)動(dòng)態(tài)聲明支持自動(dòng)結(jié)束。使用這項(xiàng)技術(shù)來(lái)改變Info.plist文件中包含NSSupportsAutomaticTermination鍵的應(yīng)用的默認(rèn)支持狀態(tài)。

Automatic Data-Saving Strategies Relieve the User

自動(dòng)數(shù)據(jù)保存方法可減輕用戶(hù)負(fù)擔(dān)

You should always avoid forcing the user to save changes to their data manually. Instead, implement automatic data saving. For a multiwindow app based onNSDocument, automatic saving is as simple as overriding theautosavesInPlace class method to return YES. For more information, seeDocument-Based App Programming Guide for Mac.

應(yīng)當(dāng)避免強(qiáng)制用戶(hù)手動(dòng)保存其數(shù)據(jù)的更改。相反,實(shí)現(xiàn)數(shù)據(jù)的自動(dòng)保存。對(duì)于基于NSDocument的多窗口應(yīng)用來(lái)說(shuō),自動(dòng)保存簡(jiǎn)單到重寫(xiě)autosavesInPlace類(lèi)方法,令其返回YES即可。有關(guān)更多信息,參考Document-Based App Programming Guide for Mac。

For a single-window, library-style app, identify appropriate points in your code where any user-related changes should be saved and write those changes to disk automatically. This benefits the user by eliminating the need to think about manually saving changes, and when done regularly, it ensures that the user does not lose much data if there is a problem.

對(duì)于單一窗口、庫(kù)類(lèi)型應(yīng)用,在代碼中確定適當(dāng)?shù)狞c(diǎn),在這些點(diǎn)上,用戶(hù)相關(guān)的變化應(yīng)自動(dòng)保存并寫(xiě)入到磁盤(pán)中。用戶(hù)無(wú)需考慮手動(dòng)保存更改,更加便利;而且定期保存還能確保一旦出現(xiàn)問(wèn)題,用戶(hù)不會(huì)丟失過(guò)多數(shù)據(jù)。

Some appropriate times when you can save user data automatically include the following:

自動(dòng)保存用戶(hù)數(shù)據(jù)的一些適當(dāng)時(shí)機(jī)如下:

When the user closes the app window or quits the app (applicationWillTerminate:)當(dāng)用戶(hù)關(guān)閉應(yīng)用窗口或退出應(yīng)用時(shí)(applicationWillTerminate:)When the app is deactivated (applicationWillResignActive:)應(yīng)用處于非活動(dòng)狀態(tài)時(shí)(applicationWillResignActive:)When the user hides your app (applicationWillHide:)用戶(hù)隱藏應(yīng)用時(shí)(applicationWillHide:)Whenever the user makes a valid change to data in your app用戶(hù)進(jìn)行了重要的數(shù)據(jù)更改時(shí)

The last item means that you have the freedom to save the user’s data at any time it makes sense to do so. For example, if the user is editing fields of a data record, you can save each field value as it is changed or you can wait and save all fields when the user displays a new record. Making these types of incremental changes ensures that the data is always up-to-date but also requires more fine-grained management of your data model. In such an instance, Core Data can help you make the changes more easily. For information about Core Data, see Core Data Starting Point.

最后一項(xiàng)意味著你有可以在任何有意義的時(shí)候保存用戶(hù)數(shù)據(jù)。例如,用戶(hù)編輯一條數(shù)據(jù)的多個(gè)條目,可以在每個(gè)條目變化時(shí)單獨(dú)保存,也可以在用戶(hù)顯示下一條數(shù)據(jù)時(shí)保存全部條目。使用這種增量更改保證了數(shù)據(jù)始終是最新的,但卻要求更加精細(xì)的數(shù)據(jù)模型管理。這種情況下,Core Data可幫助你更輕松的處理變動(dòng)。關(guān)于Core Data的信息,參考Core Data Starting Point.

Sudden Termination

立即結(jié)束

Sudden termination lets the system know that your app’s process can be killed directly without any additional involvement from your app. The benefit of supporting sudden termination is that it lets the system close apps more quickly, which is important when the user is shutting down a computer or logging out.

立即結(jié)束讓系統(tǒng)知道應(yīng)用進(jìn)程可以直接結(jié)束,而與應(yīng)用無(wú)任何牽連。支持立即結(jié)束的好處是允許系統(tǒng)更快地結(jié)束應(yīng)用,這在用戶(hù)關(guān)閉計(jì)算機(jī)或登錄的時(shí)候非常重要。

An app has two ways to declare its support for sudden termination:

應(yīng)用有兩種方式聲明支持立即結(jié)束:

Include the NSSupportsSuddenTermination key (with the valueYES) in the app’s Info.plist file.在應(yīng)用的Info.plist文件中包含NSSupportsSuddenTermination鍵(值設(shè)置為YES)。Use the NSProcessInfo class to declare support for sudden termination dynamically. You can also use this class to change the default support of an app that includes theNSSupportsSuddenTermination key in itsInfo.plist file.使用NSProcessInfo類(lèi)動(dòng)態(tài)聲明支持立即結(jié)束。使用這項(xiàng)技術(shù)來(lái)改變Info.plist文件中包含NSSupportsSuddenTermination鍵的應(yīng)用的默認(rèn)支持狀態(tài)。

One solution is to declare global support for the feature globally and then manually override the behavior at appropriate times. Because sudden termination means the system can kill your app at any time after launch, you should disable it while performing actions that might lead to data corruption if interrupted. When the action is complete, reenable the feature again.

一種解決方案是全局聲明支持這種特性,并在恰當(dāng)?shù)臅r(shí)機(jī)手動(dòng)重寫(xiě)這種行為。由于立即結(jié)束意味著當(dāng)應(yīng)用啟動(dòng)之后,系統(tǒng)能隨時(shí)結(jié)束應(yīng)用,所以在執(zhí)行一旦被打斷會(huì)導(dǎo)致數(shù)據(jù)損壞的操作時(shí),應(yīng)當(dāng)禁用它。當(dāng)那個(gè)操作結(jié)束后,再將此特此啟用。

You disable and enable sudden termination programmatically using thedisableSuddenTermination and enableSuddenTermination methods of the NSProcessInfo class. These methods increment and decrement a counter, respectively, maintained by the process. When the value of this counter is 0, the process is eligible for sudden termination. When the value is greater than 0, sudden termination is disabled.

使用NSProcessInfo類(lèi)的disableSuddenTermination和enableSuddenTermination方法來(lái)禁用和啟用立即終結(jié)。這些方法分別對(duì)應(yīng)一個(gè)計(jì)數(shù)器,由進(jìn)程維護(hù)。當(dāng)計(jì)數(shù)器的值為0時(shí),進(jìn)程可被立即結(jié)束。當(dāng)這個(gè)值大于0時(shí),立即結(jié)束被禁用。

Enabling and disabling sudden termination dynamically also means that your app should save data progressively and not rely solely on user actions to save important information. The best way to ensure that your app’s information is saved at appropriate times is to support the interfaces in OS X v10.7 for saving your document and window state. Those interfaces facilitate the automatic saving of relevant user and app data. For more information about saving your user interface state, seeUser Interface Preservation. For more information about saving your documents, seeDocument-Based Apps Are Based on an NSDocument Subclass.

動(dòng)態(tài)啟用和禁用立即結(jié)束意味著應(yīng)用應(yīng)當(dāng)循序漸進(jìn)地保存數(shù)據(jù),而不應(yīng)單純依靠用戶(hù)來(lái)保存重要信息。確保應(yīng)用信息在恰當(dāng)?shù)臅r(shí)候被保存,最好的辦法是支持OS X v10.7中保存文檔和窗口狀態(tài)的接口。這些接口簡(jiǎn)化了自動(dòng)保存用戶(hù)和應(yīng)用數(shù)據(jù)的任務(wù)。 有關(guān)保存用戶(hù)界面狀態(tài)的更多信息,參考User Interface Preservation。有關(guān)保存文檔的更多信息,參考Document-Based Apps Are Based on an NSDocument Subclass。

For additional information about enabling and disabling sudden termination, seeNSProcessInfo Class Reference.

有關(guān)啟用和禁用立即結(jié)束的更多信息,參考NSProcessInfo Class Reference。

User Interface Preservation

用戶(hù)界面保存

The Resume feature, in OS X v10.7 and later, saves the state of your app’s windows and restores them during subsequent launches of your app. Saving the state of your windows enables you to return your app to the state it was in when the user last used it. Use the Resume feature especially if your app supports automatic termination, which can cause your app to be terminated while it is running but hidden from the user. If your app supports automatic termination but does not preserve its interface, the app launches into its default state. Users who only switched away from your app might think that the app crashed while it was not being used.

在OS X v10.7及其之后的恢復(fù)功能,保存應(yīng)用窗口的狀態(tài),并在下次啟動(dòng)應(yīng)用時(shí)恢復(fù)它們。保存窗口狀態(tài)允許恢復(fù)應(yīng)用至用戶(hù)上次使用它時(shí)的狀態(tài)。盡量使用恢復(fù)功能,特別是應(yīng)用支持自動(dòng)結(jié)束時(shí),自動(dòng)結(jié)束會(huì)導(dǎo)致雖然正在運(yùn)行但已被用戶(hù)隱藏的應(yīng)用結(jié)束。如果應(yīng)用支持自動(dòng)結(jié)束卻不保存界面,應(yīng)用會(huì)以默認(rèn)狀態(tài)啟動(dòng)。僅僅是從應(yīng)用切換出來(lái)的用戶(hù)可能會(huì)認(rèn)為它在沒(méi)被使用期間崩潰了。

Writing Out the State of Your Windows and Custom Objects

寫(xiě)出窗口和其它自定義對(duì)象的狀態(tài)

You must do the following to preserve the state of your user interface:

為保存用戶(hù)界面狀態(tài),需做以下工作:

For each window, you must set whether the window should be preserved using thesetRestorable: method.對(duì)每個(gè)窗口,應(yīng)當(dāng)使用setRestorable:方法設(shè)置其是否應(yīng)當(dāng)被保存。For each preserved window, you must specify an object whose job is to re-create that window at launch time.對(duì)于每個(gè)保存的窗口,必須明確一個(gè)對(duì)象,在下次啟動(dòng)時(shí)重建窗口。Any objects involved in your user interface must write out the data they require to restore their state later.用戶(hù)界面相關(guān)的所有對(duì)象都需要將稍后恢復(fù)狀態(tài)所需的數(shù)據(jù)記錄下來(lái)。At launch time, you must use the provided data to restore your objects to their previous state.在啟動(dòng)期間,要使用提供的數(shù)據(jù)來(lái)將對(duì)象恢復(fù)至之前的狀態(tài)。

The actual process of writing out your application state to disk and restoring it later is handled by Cocoa, but you must tell Cocoa what to save. Your app’s windows are the starting point for all save operations. Cocoa iterates over all of your app’s windows and saves data for the ones whose isRestorable method returns YES. Most windows are preserved by default, but you can change the preservation state of a window using thesetRestorable: method.

將應(yīng)用程序狀態(tài)寫(xiě)入磁盤(pán)及稍后恢復(fù)的實(shí)際過(guò)程是由Cocoa處理的,但你必須告訴Cocoa要保存什么。應(yīng)用窗口是所有保存操作的起始點(diǎn)。Cocoa遍歷應(yīng)用的所有窗口,并保存那些isRestorable方法返回YES的窗口。大多數(shù)窗口是采用默認(rèn)方式保存的,但也可以使用setRestorable:方法來(lái)改變窗口的保存狀態(tài)。

In addition to preserving your windows, Cocoa saves data for most of the responder objects associated with the window. Specifically, it saves the views and window controller objects associated with the window. (For a multiwindow document-based app, the window controller also saves data from its associated document object.) Figure 2-8 shows the path that Cocoa takes when determining which objects to save. Window objects are always the starting point, but other related objects are saved, too.

除保存窗口之外,Cocoa還為與窗口關(guān)聯(lián)的大多數(shù)響應(yīng)者對(duì)象保存了數(shù)據(jù)。更確切的說(shuō),它保存了與窗口關(guān)聯(lián)的視圖和窗口控制器。(對(duì)于多窗口基于文檔的應(yīng)用,窗口控制器還從與其關(guān)聯(lián)的文檔對(duì)象保存數(shù)據(jù)。)表2-8展示了當(dāng)決定哪個(gè)對(duì)象要保存時(shí)Cocoa遵循的路徑。窗口對(duì)象總是起始點(diǎn),但其它相關(guān)對(duì)象也被保存了。

Figure 2-8  Responder objects targeted by Cocoa for preservation

表2-8 被Cocoa設(shè)定為保存目標(biāo)的響應(yīng)者對(duì)象

All Cocoa window and view objects save basic information about their size and location, plus information about other attributes that might affect the way they are currently displayed. For example, a tab view saves the index of the selected tab, and a text view saves the location and range of the current text selection. However, these responder objects do not have any inherent knowledge about your app’s data structures. Therefore, it is your responsibility to save your app’s data and any additional information needed to restore the window to its current state. There are several places where you can write out your custom state information:

所有Cocoa窗口和視圖對(duì)象保存基本的大小和位置信息,以及可能影響它們當(dāng)前顯示方式的其它屬性信息。例如,標(biāo)簽視圖保存當(dāng)前選擇標(biāo)簽的序號(hào),文本視圖保存當(dāng)前選擇文本的位置和范圍。然而,這些響應(yīng)者對(duì)象不含有關(guān)于應(yīng)用數(shù)據(jù)結(jié)構(gòu)的任何內(nèi)存信息。因此,保存恢復(fù)窗口至當(dāng)前狀態(tài)所需的應(yīng)用數(shù)據(jù)和其它信息,是你要完成的任務(wù)。可在下列位置記錄你的自定義狀態(tài)信息:

If you subclass NSWindow or NSView, implement the encodeRestorableStateWithCoder: method in your subclass and use it to write out any relevant data. Alternatively, your customresponder objects can override therestorableStateKeyPaths method and use it to specify key paths for any attributes to be preserved. Cocoa uses the key paths to locate and save the data for the corresponding attribute. Attributes must be compliant withkey-value coding and Key-value observing.如果繼承了NSWindow或NSView,在子類(lèi)中實(shí)現(xiàn)encodeRestorableStateWithCoder:方法,使用它來(lái)記錄相關(guān)數(shù)據(jù)。或者,你自定義的響應(yīng)者對(duì)象可重寫(xiě)restorableStateKeyPaths方法,使用它來(lái)指定要保存屬性的鍵路徑。Cocoa使用鍵路徑為相應(yīng)屬性定位和保存數(shù)據(jù)。屬性必須遵從鍵-值編碼和鍵-值觀察。If your window has a delegate object, implement the window:willEncodeRestorableState: method for the delegate and use it to store any relevant data.如果窗口擁有代理對(duì)象,實(shí)現(xiàn)代理的window:willEncodeRestorableState:方法,使用它來(lái)保存相關(guān)數(shù)據(jù)。In your window controller, use the encodeRestorableStateWithCoder: method to save any relevant data or configuration information.在窗口控制器中,使用encodeRestorableStateWithCoder:方法來(lái)保存數(shù)據(jù)和配置信息。

Be judicious when deciding what data to preserve, and strive to write out the smallest amount of information that is required to reconfigure your window and associated objects. You are expected to save the actual data that the window displays and enough information to reattach the window to the same data objects later.

合理選擇要保存的數(shù)據(jù),盡可能少地記錄重新配置窗口和其關(guān)聯(lián)對(duì)象所需的信息。還需要記錄窗口顯示的實(shí)際數(shù)據(jù),以及將窗口重新關(guān)聯(lián)到同一數(shù)據(jù)對(duì)象所需的足夠信息。

Important: Never use the user interface preservation mechanism as a way to save your app’s actual data. The archive created for interface preservation can change frequently and may be ignored altogether if there is a problem during the restoration process. Your app data should always be saved independently in data files that are managed by your app.

重要提示:決不要將用戶(hù)界面保存機(jī)制用作保存應(yīng)用實(shí)際數(shù)據(jù)的一種方式。為界面恢復(fù)所創(chuàng)建的包會(huì)經(jīng)常變化,而且如果在恢復(fù)過(guò)程中出現(xiàn)問(wèn)題,這個(gè)包會(huì)被完全忽略。應(yīng)用數(shù)據(jù)應(yīng)當(dāng)獨(dú)立保存在由應(yīng)用管理的數(shù)據(jù)文件中。

For information on how to use coder objects to archive state information, seeNSCoder Class Reference. For additional information on what you need to do to save state in a multiwindow document-based app, seeDocument-Based App Programming Guide for Mac.

關(guān)于如何使用編碼對(duì)象來(lái)打包狀態(tài)信息,參考NSCoder Class Reference。關(guān)于在多窗口基于文檔應(yīng)用中保存狀態(tài)所需工作的信息,參考Document-Based App Programming Guide for Mac。

Notifying Cocoa About Changes to Your Interface State

將界面狀態(tài)的變化通知Cocoa

Whenever the preserved state of one of your responder objects changes, mark the object as dirty by calling theinvalidateRestorableState method of that object. Having done so, at some point in the future,encodeRestorableStateWithCoder: message is sent to your responder object. Marking your responder objects as dirty lets Cocoa know that it needs to write their preservation state to disk at an appropriate time. Invalidating your objects is a lightweight operation in itself because the data is not written to disk right away. Instead, changes are coalesced and written at key times, such as when the user switches to another app or logs out.

每當(dāng)一個(gè)響應(yīng)者對(duì)象的保存狀態(tài)變化時(shí),通過(guò)調(diào)用該對(duì)象的invalidateRestorableState方法,將其標(biāo)記為已變化(dirty)。這樣操作后,在將來(lái)的某個(gè)點(diǎn),encodeRestorableStateWithCoder:消息會(huì)被發(fā)送到響應(yīng)者對(duì)象。將響應(yīng)者標(biāo)記為已變化讓Cocoa知道它需要在恰當(dāng)?shù)臅r(shí)候?qū)⒈4鏍顟B(tài)寫(xiě)入到磁盤(pán)。將對(duì)象設(shè)置為無(wú)效是一個(gè)輕量級(jí)操作,因?yàn)閿?shù)據(jù)不會(huì)立即寫(xiě)入到磁盤(pán)。相反,在諸如用戶(hù)切換到另外的應(yīng)用或退出登錄等關(guān)鍵時(shí)刻,變化會(huì)被合并及寫(xiě)入。

You should mark a responder object as dirty only for changes that are truly interface related. For example, a tab view marks itself as dirty when the user selects a different tab. However, you do not need to invalidate your window or its views for many content-related changes, unless the content changes themselves caused the window to be associated with a completely different set of data-providing objects.

應(yīng)當(dāng)在響應(yīng)者對(duì)象確實(shí)發(fā)生了與界面相關(guān)的變化時(shí),再將其標(biāo)記為已變化。例如,當(dāng)用戶(hù)選擇了一個(gè)不同的標(biāo)簽時(shí),標(biāo)簽視圖才將自身標(biāo)記為已變化。然而,不必為許多內(nèi)容相關(guān)的變化,而將窗口或其視圖設(shè)置為無(wú)效,除非內(nèi)容本身的變化導(dǎo)致窗口關(guān)聯(lián)到了另一套完全不同的數(shù)據(jù)提供對(duì)象。

If you used the restorableStateKeyPaths method to declare the attributes you want to preserve, Cocoa preserves and restores the values of those attributes of your responder object. Therefore, any key paths you provide should bekey-value observing compliant and generate the appropriate notifications. For more information on how to support key-value observing in your objects, seeKey-Value Observing Programming Guide.

如果使用restorableStateKeyPaths方法來(lái)聲明需要保存的屬性,Cocoa會(huì)保存和恢復(fù)響應(yīng)者對(duì)象的這些屬性。因此,你提供的關(guān)鍵路徑應(yīng)當(dāng)遵從鍵-值觀察并產(chǎn)生合適的通知。關(guān)于如何在對(duì)象中支持鍵-值觀察,參考Key-Value Observing Programming Guide。

Restoring Your Windows and Custom Objects at Launch Time

在啟動(dòng)時(shí)恢復(fù)窗口和自定義對(duì)象

As part of your app’s normal launch cycle, Cocoa checks to see whether there is any preserved interface data. If there is, Cocoa uses that data to try to re-create your app’s windows. Every window must identify a restoration class that knows about the window and can act on its behalf at launch time to create the window when asked to do so by Cocoa.

作為應(yīng)用正常啟動(dòng)周期的一部分,Cocoa會(huì)檢查是否有保存的界面數(shù)據(jù)。如果有,Cocoa使用這些數(shù)據(jù)來(lái)嘗試重建應(yīng)用窗口。每個(gè)窗口必須明確一個(gè)知道關(guān)于此窗口的恢復(fù)類(lèi),并且當(dāng)Cocoa要求恢復(fù)時(shí),能夠代表自身創(chuàng)建窗口。

The restoration class is responsible for creating both the window and all of the critical objects required by that window. For most app styles, the restoration class usually creates one or more controller objects as well. For example, in a single-window app, the restoration class would likely create the window controller used to manage the window and then retrieve the window from that object. Because it creates these controller objects too, you typically use high-level application classes for your restoration classes. An app might use the application delegate, a document controller, or even a window controller as a restoration class.

恢復(fù)類(lèi)負(fù)責(zé)創(chuàng)建窗口及其所需的所有關(guān)鍵對(duì)象。對(duì)于大多數(shù)應(yīng)用來(lái)說(shuō),恢復(fù)類(lèi)通常會(huì)同時(shí)創(chuàng)建一個(gè)或多個(gè)控制器對(duì)象。例如,在單一窗口應(yīng)用中,恢復(fù)類(lèi)可能會(huì)創(chuàng)建用于管理窗口的窗口控制器,并從中獲取窗口。由于它創(chuàng)建這些控制器對(duì)象,所以通常使用高層應(yīng)用程序類(lèi)作為恢復(fù)類(lèi)。應(yīng)用可能使用應(yīng)用程序代理、文檔控制器或者窗口控制器作為恢復(fù)類(lèi)。

During the launch cycle, Cocoa restores each preserved window as follows:

在啟動(dòng)周期內(nèi),Cocoa按如下步驟來(lái)恢復(fù)保存的窗口:

Cocoa retrieves the window’s restoration class from the preserved data and calls itsrestoreWindowWithIdentifier:state:completionHandler: class method.Cocoa從保存的數(shù)據(jù)中獲取窗口的恢復(fù)類(lèi),并調(diào)用其restoreWindowWithIdentifier:state:completionHandler:類(lèi)方法。The restoreWindowWithIdentifier:state:completionHandler: class method must call the provided completion handler with the desired window object. To do this, it does one of the following:restoreWindowWithIdentifier:state:completionHandler:類(lèi)方法必須使用要求的窗口對(duì)象來(lái)調(diào)用提供的完成塊。為做到這一點(diǎn),它需要完成下列工作之一:It creates any relevant controller objects (including the window controller) that might normally be created to display the window.它創(chuàng)建相關(guān)的控制器對(duì)象(包括窗口控制器),這些對(duì)象通常被用于顯示窗口。If the controller objects already exist (perhaps because they were already loaded from a nib file), the method gets the window from those existing objects.如果控制器對(duì)象已經(jīng)存在(可能是由于它們已經(jīng)從nib文件中加載了),這個(gè)方法從這些已經(jīng)存在的對(duì)象中獲取窗口。If the window could not be created, perhaps because the associated document was deleted by the user, therestoreWindowWithIdentifier:state:completionHandler: should pass an error object to the completion handler.如果無(wú)法創(chuàng)建窗口,可能是由于相關(guān)的文檔被用戶(hù)刪除了,restoreWindowWithIdentifier:state:completionHandler:方法應(yīng)當(dāng)向完成塊傳遞一個(gè)error對(duì)象。Cocoa uses the returned window to restore it and any preserved responder objects to their previous state.Cocoa使用返回的窗口來(lái)恢復(fù)它及保存的響應(yīng)者對(duì)象至之前的狀態(tài)。Standard Cocoa window and view objects are restored to their previous state without additional help. If you subclassNSWindow orNSView, implement therestoreStateWithCoder: method to restore any custom state. If you implemented therestorableStateKeyPaths method in your custom responder objects, Cocoa automatically sets the value of the associated attributes to their preserved values. Thus, you do not have to implement the restoreStateWithCoder: to restore these attributes.標(biāo)準(zhǔn)的Cocoa窗口和視圖對(duì)象可被恢復(fù)到它們之前的狀態(tài),而無(wú)需額外幫助。如果繼承了NSWindow或NSView,實(shí)現(xiàn)restoreStateWithCoder:方法來(lái)恢復(fù)自定義狀態(tài)。如果在自定義響應(yīng)者對(duì)象中實(shí)現(xiàn)了restorableStateKeyPaths方法,Cocoa會(huì)自動(dòng)將相關(guān)屬性設(shè)置為保存的值,因此,你不必實(shí)現(xiàn)restoreStateWithCoder:方法來(lái)恢復(fù)這些屬性。For the window delegate object, Cocoa calls the window:didDecodeRestorableState: method to restore the state of that object.對(duì)于窗口代理對(duì)象,Cocoa調(diào)用window:didDecodeRestorableState:方法來(lái)恢復(fù)其狀態(tài)。For your window controller, Cocoa calls the restoreStateWithCoder: method to restore its state.對(duì)于窗口控制器,Cocoa調(diào)用restoreStateWithCoder:方法來(lái)恢復(fù)其狀態(tài)。

When re-creating each window, Cocoa passes the window’s unique identifier string to the restoration class. You are responsible for assigning user interface identifier strings to your windows prior to preserving the window state. You can assign an identifier in your window’s nib file or by setting your window object's identifier property (defined in NSUserInterfaceItemIdentification protocol). For example, you might give your preferences window an identifier ofpreferences and then check for that identifier in your implementation. Your restoration class can use this identifier to determine which window and associated objects it needs to re-create. The contents of an identifier string can be anything you want but should be something to help you identify the window later.

當(dāng)恢復(fù)窗口時(shí),Cocoa將該窗口的唯一辨識(shí)符字符串傳遞給恢復(fù)類(lèi)。在保存窗口狀態(tài)之前,要為窗口分配用戶(hù)界面辨識(shí)字符串。可在窗口的nib文件中指定辨識(shí)符,或者設(shè)置窗口對(duì)象的identifier屬性(在NSUserInterfaceItemIdentification協(xié)議中定義)。例如,你可能為偏好窗口設(shè)置了preferences辨識(shí)符,就可在實(shí)現(xiàn)中檢查它。恢復(fù)類(lèi)可使用這個(gè)辨識(shí)符來(lái)決定它需要重建哪個(gè)窗口及其相關(guān)聯(lián)的對(duì)象。辨識(shí)符字符串的內(nèi)容可以是任何你想要的內(nèi)容,但應(yīng)當(dāng)是以后能幫助你辨識(shí)該窗口的東西。

For a single-window app whose main window controller and window are loaded from the main nib file, the job of your restoration class is fairly straightforward. Here, you could use the application delegate’s class as the restoration class and implement the restoreWindowWithIdentifier:state:completionHandler: method similar to the implementation shown in Listing 2-2. Because the app has only one window, it returns the main window directly. If you used the application delegate’s class as the restoration class for other windows, your own implementation could use the identifier parameter to determine which window to create.

對(duì)于一個(gè)窗口控制器和窗口均從主nib文件加載的單一窗口應(yīng)用來(lái)說(shuō),恢復(fù)類(lèi)的工作相當(dāng)直接。在這里,你可以使用應(yīng)用代理類(lèi)作為恢復(fù)類(lèi),并實(shí)現(xiàn)與列表2-2中類(lèi)似的restoreWindowWithIdentifier:state:completionHandler:方法。由于應(yīng)用只有一個(gè)窗口,它直接返回主窗口。如果使用應(yīng)用代理類(lèi)作為其它窗口的恢復(fù)類(lèi),在實(shí)現(xiàn)中可使用辨識(shí)符參數(shù)來(lái)決定創(chuàng)建哪個(gè)窗口。

Listing 2-2  Returning the main window for a single-window app

列表2-2 為單一窗口應(yīng)用返回主窗口

+ (void)restoreWindowWithIdentifier:(NSString *)identifier        state:(NSCoder *)state        completionHandler:(void (^)(NSWindow *, NSError *))completionHandler{   // Get the window from the window controller,   // which is stored as an outlet by the delegate.   // Both the app delegate and window controller are   // created when the main nib file is loaded.   MyAppDelegate* appDelegate = (MyAppDelegate*)[[NSApplication sharedApplication] delegate];   NSWindow* mainWindow = [appDelegate.windowController window];   // Pass the window to the provided completion handler.   completionHandler(mainWindow, nil);}

Apps Are Built Using Many Different Pieces

應(yīng)用使用許多不同的部件來(lái)構(gòu)建

The objects of the core architecture are important but are not the only objects you need to consider in your design. The core objects manage the high-level behavior of your app, but the objects in your app’s view layer do most of the work to display your custom content and respond to events. Other objects also play important roles in creating interesting and engaging apps.

在應(yīng)用設(shè)計(jì)中,核心架構(gòu)的對(duì)象很重要,但它們并不是唯一需要考慮的對(duì)象。核心對(duì)象管理應(yīng)用的高級(jí)特性,但應(yīng)用視圖層的對(duì)象做了顯示內(nèi)容、響應(yīng)事件的大多數(shù)工作。在創(chuàng)建有趣、迷人的應(yīng)用中,其它對(duì)象也發(fā)揮了重要作用。

The User Interface

用戶(hù)界面

An app’s user interface is made up of a menu bar, one or more windows, and one or more views. The menu bar is a repository for commands that the user can perform in the app. Commands may apply to the app as a whole, to the currently active window, or to the currently selected object. You are responsible for defining the commands that your app supports and for providing the event-handling code to respond to them.

應(yīng)用用戶(hù)界面由一個(gè)菜單欄、一個(gè)或多個(gè)窗口、一個(gè)或多個(gè)視圖組成。菜單欄是用戶(hù)可執(zhí)行的命令容器。命令可應(yīng)用到應(yīng)用程序整體、當(dāng)前活動(dòng)窗口或當(dāng)前選擇的對(duì)象。你負(fù)責(zé)定義應(yīng)用支持的命令,并提供響應(yīng)它們所需的事件處理代碼。

You use windows and views to present your app’s visual content on the screen and to manage the immediate interactions with that content. A window is an instance of theNSWindow class. A panel is an instance of theNSPanel class (which is a descendant ofNSWindow) that you use to present secondary content. Single-window apps have one main window and may have one or more secondary windows or panels. Multiwindow apps have multiple windows for displaying their primary content and may have one or more secondary windows or panels too. The style of a window determines its appearance on the screen. Figure 2-9 shows the menu bar, along with some standard windows and panels.

使用窗口和視圖在屏幕上呈現(xiàn)應(yīng)用的可視化內(nèi)容,并管理與這些內(nèi)容的即時(shí)交互。窗口是NSWindow類(lèi)的實(shí)例。面板是NSPanel類(lèi)(它是NSWindow的子類(lèi))的實(shí)例,用來(lái)呈現(xiàn)二級(jí)內(nèi)容。單一窗口應(yīng)用擁有一個(gè)主窗口以及一個(gè)或多個(gè)二級(jí)窗口或面板。多窗口應(yīng)用擁有多個(gè)窗口來(lái)展示主要內(nèi)容,也可擁有一個(gè)或多個(gè)二級(jí)窗口或面板。窗口的樣式?jīng)Q定其在屏幕上的外觀。圖2-9顯示了菜單欄以及一些標(biāo)準(zhǔn)化的窗口和面板。

Figure 2-9  Windows and menus in an app

圖2-9 應(yīng)用的窗口和菜單

A view, an instance of the NSView class, defines the content for a rectangular region of a window. Views are the primary mechanism for presenting content and interacting with the user and have several responsibilities. For example:

視圖是NSView類(lèi)的實(shí)例,定義了窗口中一個(gè)矩形區(qū)域的內(nèi)容。視圖是呈現(xiàn)內(nèi)容和與用戶(hù)交互的主要機(jī)制,負(fù)有許多職責(zé)。例如:

Drawing and animation support. Views draw content in their rectangular area. Views that support Core Animation layers can use those layers to animate their contents.繪圖和動(dòng)畫(huà)支持。視圖在其矩形區(qū)域內(nèi)繪制內(nèi)容。支持Core Animation層的視圖可使用這些層為其內(nèi)容添加動(dòng)畫(huà)。Layout and subview management. Each view manages a list of subviews, allowing you to create arbitrary view hierarchies. Each view defines layout and resizing behaviors to accommodate changes in the window size.布局和子視圖管理。視圖管理一系列子視圖,允許你創(chuàng)建任意視圖層級(jí)。視圖定義布局和縮放行為,來(lái)適應(yīng)窗口大小的變化。Event handling. Views receive events. Views forward events to other objects when appropriate.事件處理。視圖接收事件。視圖根據(jù)需要將事件傳遞給其它對(duì)象。

For information about creating and configuring windows, see Window Programming Guide. For information about using and creating view hierarchies, seeView Programming Guide.

有關(guān)創(chuàng)建和配置窗口的信息,參考Window Programming Guide。有關(guān)使用和創(chuàng)建視圖層級(jí)的信息,參考View Programming Guide。

Event Handling

事件處理

The system window server is responsible for tracking mouse, keyboard, and other events and delivering them to your app. When the system launches an app, it creates both a process and a single thread for the app. This initial thread becomes the app’s main thread. In it, the NSApplication object sets up the main run loop and configures its event-handling code, as shown in Figure 2-10. As the window server delivers events, the app queues those events and then processes them sequentially in the app’s main run loop. Processing an event involves dispatching the event to the object best suited to handle it. For example, mouse events are usually dispatched to the view in which the event occurred.

系統(tǒng)窗口服務(wù)器負(fù)責(zé)追蹤鼠標(biāo)、鍵盤(pán)及其它事件,并將它們發(fā)送到你的應(yīng)用。當(dāng)系統(tǒng)啟動(dòng)應(yīng)用時(shí),為應(yīng)用同時(shí)創(chuàng)建一個(gè)進(jìn)程和一個(gè)單一線(xiàn)程。這個(gè)初始化的線(xiàn)程成為應(yīng)用的主線(xiàn)程。在這個(gè)主線(xiàn)程中,NSApplication對(duì)象建立主運(yùn)行循環(huán),配置其事件處理代碼,如圖2-10所示。當(dāng)窗口服務(wù)器發(fā)送事件時(shí),應(yīng)用將事件存入隊(duì)列,然后按順序在主運(yùn)行循環(huán)上執(zhí)行它們。處理事件就是將其分派到最適合處理它的對(duì)象上。例如,鼠標(biāo)事件通常被分派到事件發(fā)生的視圖上。

Figure 2-10  Processing events in the main run loop

圖2-20 在主運(yùn)行循環(huán)中處理事件

Note: A run loop monitors sources of input on a specific thread of execution. The app’s event queue represents one of these input sources. While the event queue is empty, the main thread sleeps. When an event arrives, the run loop wakes up the thread and dispatches control to the NSApplication object to handle the event. After the event has been handled, control passes back to the run loop, which can then process another event, process other input sources, or put the thread back to sleep if there is nothing more to do. For more information about how run loops and input sources work, seeThreading Programming Guide.

提示:運(yùn)行循環(huán)在一個(gè)特殊的執(zhí)行線(xiàn)程上監(jiān)視輸入源。應(yīng)用事件隊(duì)列表示的是這些輸入源之一。當(dāng)事件隊(duì)列為空時(shí),主線(xiàn)程睡眠。當(dāng)一個(gè)事件到達(dá)時(shí),運(yùn)行循環(huán)喚醒線(xiàn)程,將控制權(quán)分派到NSApplication對(duì)象,來(lái)處理事件。事件處理完成后,控制權(quán)被交回至主循環(huán)。主循環(huán)繼續(xù)處理其它事件或其它輸入源,如果無(wú)事可做,則使線(xiàn)程睡眠。關(guān)于運(yùn)行循環(huán)和輸入源工作的更多信息,參考Threading Programming Guide。

Distributing and handling events is the job of responder objects, which are instances of theNSResponder class. The NSApplication,NSWindow,NSDrawer,NSView,NSWindowController, and NSViewController classes are all descendants of NSResponder. After pulling an event from the event queue, the app dispatches that event to the window object where it occurred. The window object, in turn, forwards the event to its first responder. In the case of mouse events, the first responder is typically the view object (NSView) in which the touch took place. For example, a mouse event occurring in a button is delivered to the corresponding button object.

分發(fā)和處理事件是響應(yīng)者對(duì)象的工作,響應(yīng)者對(duì)象是NSResponder類(lèi)的實(shí)例。NSApplication、NSWindow、NSDrawer,、NSView,、NSWindowController和NSViewController類(lèi)都是NSResponder的子類(lèi)。將一個(gè)事件從事件隊(duì)列取出后,應(yīng)用將事件分配到事件發(fā)生的窗口對(duì)象上。窗口對(duì)象依次將事件傳遞給它的第一響應(yīng)者。對(duì)于鼠標(biāo)事件來(lái)說(shuō),第一響應(yīng)者通常是點(diǎn)擊發(fā)生所在的視圖對(duì)象。例如,在一個(gè)按鈕上發(fā)生的鼠標(biāo)事件,會(huì)傳遞到相應(yīng)的按鈕對(duì)象上,

If the first responder is unable to handle an event, it forwards the event to its next responder, which is typically a parent view, view controller, or window. If that object is unable to handle the event, it forwards it to its next responder, and so on, until the event is handled. This series of linked responder objects is known as the responder chain. Messages continue traveling up the responder chain—toward higher-level responder objects, such as a window controller or the application object—until the event is handled. If the event isn't handled, it is discarded.

如果第一響應(yīng)者無(wú)法處理事件,它會(huì)將事件向前傳遞至下一個(gè)響應(yīng)者,可能是父視圖、視圖控制器或窗口。如果這個(gè)新的響應(yīng)者也無(wú)法處理,它后繼續(xù)向前傳遞,直至事件被處理。這些相聯(lián)的一系列響應(yīng)者對(duì)象被稱(chēng)為響應(yīng)者鏈。消息沿著響應(yīng)者鏈持續(xù)向上傳遞——朝著高層的響應(yīng)者對(duì)象,如窗口控制器或應(yīng)用程序?qū)ο蟆敝潦录惶幚怼H绻录o(wú)法處理,它會(huì)被丟棄。

The responder object that handles an event often sets in motion a series of programmatic actions by the app. For example, a control object (that is, a subclass ofNSControl) handles an event by sending an action message to another object, typically the controller that manages the current set of active views. While processing the action message, the controller might change the user interface or adjust the position of views in ways that require some of those views to redraw themselves. When this happens, the view and graphics infrastructure takes over and processes the required redraw events in the most efficient manner possible.

處理事件的響應(yīng)者通常由應(yīng)用設(shè)置一系列程序動(dòng)作。例如,一個(gè)控件對(duì)象(NSControl類(lèi)的子類(lèi))處理事件時(shí),會(huì)向其它對(duì)象發(fā)送一條動(dòng)作信息,這個(gè)其它對(duì)象通常是管理當(dāng)前活動(dòng)視圖的控制器。處理動(dòng)作消息時(shí),控制器可能會(huì)采用要求這些視圖進(jìn)行重繪的方式,改變用戶(hù)界面或調(diào)整視圖位置。這種情況發(fā)生時(shí),視圖和圖形基礎(chǔ)設(shè)施開(kāi)始接管,并使用最有效的方式來(lái)處理要求的重繪事件。

For more information about responders, the responder chain, and handling events, seeCocoa Event Handling Guide.

關(guān)于響應(yīng)者、響應(yīng)者鏈和處理事件的更多信息,參考Cocoa Event Handling Guide。

Graphics, Drawing, and Printing

圖形、繪制和打印

There are two basic ways in which a Mac app can draw its content:

Mac應(yīng)用使用兩種基礎(chǔ)方式來(lái)繪制其內(nèi)容:

Native drawing technologies (such as Core Graphics and AppKit)原生的繪制技術(shù)(比如Core Graphics和AppKit)OpenGL開(kāi)放圖形庫(kù)(Open Graphics Library)

The native OS X drawing technologies typically use the infrastructure provided by Cocoa views and windows to render and present custom content. When a view is first shown, the system asks it to draw its content. System views draw their contents automatically, but custom views must implement a drawRect: method. Inside this method, you use the native drawing technologies to draw shapes, text, images, gradients, or any other visual content you want. When you want to update your view’s visual content, you mark all or part of the view invalid by calling its setNeedsDisplay: or setNeedsDisplayInRect: method. The system then calls your view’sdrawRect: method (at an appropriate time) to accommodate the update. This cycle then repeats and continues throughout the lifetime of your app.

原生的OS X繪制技術(shù)通常使用Cocoa視圖和窗口提供的基礎(chǔ)設(shè)施來(lái)渲染和呈現(xiàn)自定義內(nèi)容。當(dāng)視圖首次顯示時(shí),系統(tǒng)要求其繪制內(nèi)容。系統(tǒng)視圖自動(dòng)繪制其內(nèi)容,但自定義視圖必須實(shí)現(xiàn)drawRect:方法。在這個(gè)方法中,使用原生繪制技術(shù)來(lái)繪制形狀、文本、圖片、漸變或其它可視化內(nèi)容。當(dāng)想要更新視圖的可視化內(nèi)容時(shí),通過(guò)調(diào)用setNeedsDisplay:或setNeedsDisplayInRect:方法,將視圖的全部或部分設(shè)置為無(wú)效。系統(tǒng)會(huì)調(diào)用視圖的drawRect:方法(在適當(dāng)?shù)臅r(shí)刻)來(lái)適應(yīng)更新。在應(yīng)用生命周期內(nèi),這個(gè)循環(huán)重復(fù)、連續(xù)。

If you are using OpenGL to draw your app’s content, you still create a window and view to manage your content, but those objects simply provide the rendering surface for an OpenGL drawing context. Once you have that drawing context, your app is responsible for initiating drawing updates at appropriate intervals.

如果使用OpenGL來(lái)繪制應(yīng)用內(nèi)容,仍需要?jiǎng)?chuàng)建窗口和視圖來(lái)管理內(nèi)容,但這些對(duì)象只簡(jiǎn)單地為OpenGL繪制上下文提供渲染平面。一旦獲取繪制上下文之后,應(yīng)用就要開(kāi)始定期更新繪圖。

For information about how to draw custom content in your views, seeCocoa Drawing Guide.

有關(guān)在視圖中繪制自定義內(nèi)容的信息,參考Cocoa Drawing Guide。

Text Handling

文本處理

The Cocoa text system, the primary text-handling system in OS X, is responsible for the processing and display of all visible text in Cocoa. It provides a complete set of high-quality typographical services through the text-related AppKit classes, which enable apps to create, edit, display, and store text with all the characteristics of fine typesetting.

Cocoa文件系統(tǒng)是OS X中的主要文本處理系統(tǒng),負(fù)責(zé)Cocoa中所有可視化文本的處理和顯示。它通過(guò)與文本相關(guān)的AppKit類(lèi)來(lái)提供一整套高質(zhì)量的印刷服務(wù)。AppKit類(lèi)允許應(yīng)用使用可良好排版的字符來(lái)創(chuàng)建、編輯、顯示和存儲(chǔ)文本。

The Cocoa text system provides all these basic and advanced text-handling features, and it also satisfies additional requirements from the ever-more-interconnected computing world: support for the character sets of all of the world’s living languages, powerful layout capabilities to handle various text directionality and nonrectangular text containers, and sophisticated typesetting capabilities such as control of kerning, ligatures, line breaking, and justification. Cocoa’s object-oriented text system is designed to provide all these capabilities without requiring you to learn about or interact with more of the system than is necessary to meet the needs of your app.

Cocoa文本系統(tǒng)提供了基礎(chǔ)且先進(jìn)的文本處理功能,同時(shí)還可滿(mǎn)足聯(lián)系緊密的計(jì)算機(jī)應(yīng)用的額外需求:支持世界上所有現(xiàn)存語(yǔ)言字符集、可處理多種不同書(shū)寫(xiě)方向和不規(guī)則文本容器的強(qiáng)大布局功能,以及諸如字距調(diào)整、連字、斷行、對(duì)齊等復(fù)雜的排版功能。Cocoa面向?qū)ο蟮奈谋鞠到y(tǒng)被設(shè)計(jì)為既能夠提供滿(mǎn)足應(yīng)用需要的所有功能,而又無(wú)需你進(jìn)行學(xué)習(xí)或與系統(tǒng)進(jìn)行過(guò)多交互。

Underlying the Cocoa text system is Core Text, which provides low-level, basic text layout and font-handling capabilities to higher-level engines such as Cocoa and WebKit. Core Text provides the implementation for many Cocoa text technologies. App developers typically have no need to use Core Text directly. However, the Core Text API is accessible to developers who must use it directly, such as those writing apps with their own layout engine and those porting older ATSUI- or QuickDraw-based codebases to the modern world.

Cocoa文本系統(tǒng)的底層是Core Text,它提供了底層、基礎(chǔ)的文本布局,也為Cocoa和WebKit等高級(jí)引擎提供了文本處理能力。Core Text為許多Cocoa文本技術(shù)提供了實(shí)現(xiàn)方法。應(yīng)用開(kāi)發(fā)者通常不需要直接訪問(wèn)Core Text。不過(guò),那些必須直接使用Core Text的開(kāi)發(fā)者,比如使用自定義布局引擎來(lái)編寫(xiě)應(yīng)用、需要將舊式的基于ATSUI或QuickDraw的編碼導(dǎo)出為最新,也可訪問(wèn)Core Text的API。

For more information about the Cocoa text system, see Cocoa Text Architecture Guide.

關(guān)于Cocoa文本系統(tǒng)的更多信息,參考Cocoa Text Architecture Guide。

Implementing the Application Menu Bar

使用應(yīng)用程序目錄欄

The classes NSMenu andNSMenuItem are the basis for all types of menus. An instance ofNSMenu manages a collection of menu items and draws them one beneath another. An instance ofNSMenuItem represents a menu item; it encapsulates all the information itsNSMenu object needs to draw and manage it, but does no drawing or event-handling itself. You typically use Interface Builder to create and modify any type of menu, so often there is no need to write any code.

NSMenu和NSMenuItem類(lèi)是所有類(lèi)型菜單的基礎(chǔ)。一個(gè)NSMenu類(lèi)的實(shí)例管理一系列的菜單項(xiàng),并逐個(gè)繪制它們。一個(gè)NSMenuItem類(lèi)的實(shí)例代表一個(gè)菜單項(xiàng);它包含NSMenu對(duì)象繪制和管理它所需的全部信息,自己卻不做繪制和事件處理的工作。通常使用界面生成器來(lái)創(chuàng)建和管理菜單,所以無(wú)需寫(xiě)任何代碼。

The application menu bar stretches across the top of the screen, replacing the menu bar of any other app when the app is foremost. All of an app’s menus in the menu bar are owned by oneNSMenu instance that’s created by the app when it starts up.

應(yīng)用程序的菜單欄橫貫于屏幕的頂部,如果應(yīng)用處于最前端,則會(huì)替換掉其它應(yīng)用的菜單欄。應(yīng)用位于菜單欄中的所有菜單者歸一個(gè)NSMenu實(shí)例所有,這個(gè)實(shí)例由應(yīng)用在啟動(dòng)時(shí)創(chuàng)建。

Xcode Templates Provide the Menu Bar

Xcode模板提供了菜單欄

Xcode’s Cocoa application templates provide that NSMenu instance in a nib file calledMainMenu.xib. This nib file contains an application menu (named with the app’s name), a File menu (with all of its associated commands), an Edit menu (with text editing commands and Undo and Redo menu items), and Format, View, Window, and Help menus (with their own menu items representing commands). These menu items, as well as all of the menu items of the File menu, are connected to the appropriate first-responder action methods. For example, the About menu item is connected to the orderFrontStandardAboutPanel: action method in the File’s Owner that displays a standard About window.

Xcode的Cocoa應(yīng)用程序模板在稱(chēng)為MainMenu.xib的nib文件中提供了NSMenu實(shí)例。這個(gè)nib文件包含一個(gè)應(yīng)用程序目錄(以應(yīng)用名稱(chēng)命名),一個(gè)文件目錄(包含相關(guān)的命令),一個(gè)編輯目錄(包含文本編輯命令和撤銷(xiāo)、重做目錄項(xiàng))和格式、視圖、窗口、幫助目錄(包含表示命令的目錄項(xiàng))。這些目錄項(xiàng)與文件目錄中的所有目錄項(xiàng)一樣,都與適當(dāng)?shù)牡谝豁憫?yīng)者動(dòng)作方法相聯(lián)。例如,關(guān)于目錄項(xiàng)與File’s Owner中orderFrontStandardAboutPanel:的方法相聯(lián),F(xiàn)ile’s Owner顯示一個(gè)標(biāo)準(zhǔn)的關(guān)于窗口。

The template has similar ready-made connections for the Edit, Format, View, Window, and Help menus. If your app does not support any of the supplied actions (for example, printing), you should remove the associated menu items (or menu) from the nib. Alternatively, you may want to repurpose and rename menu commands and action methods to suit your own app, taking advantage of the menu mechanism in the template to ensure that everything is in the right place.

模板擁有已創(chuàng)建的編輯、格式、視圖、窗口和幫助目錄的連接。如果應(yīng)用不支持提供的動(dòng)作(比如打印),應(yīng)當(dāng)在nib中刪除相關(guān)的目錄項(xiàng)。或者,你可能想對(duì)目錄命令或操作方法進(jìn)行重定義或重命名,利用好模板中的菜單機(jī)制,確保一切順利。

Connect Menu Items to Your Code or Your First Responder

將目錄項(xiàng)連接至代碼或第一響應(yīng)者

For your app’s custom menu items that are not already connected to action methods in objects or placeholder objects in the nib file, there are two common techniques for handling menu commands in a Mac app:

對(duì)于應(yīng)用中的自定義目錄項(xiàng),它們尚未連接到nib文件中的對(duì)象或占位符對(duì)象的操作方法,在Mac應(yīng)用中有兩種常用技術(shù)來(lái)處理目錄命令:

Connect the corresponding menu item to a first responder method.將相應(yīng)的目錄項(xiàng)連接到第一響應(yīng)者對(duì)象的一個(gè)方法。Connect the menu item to a method of your custom application object or your application delegate object.將目錄項(xiàng)連接到自定義應(yīng)用程序?qū)ο蠡驊?yīng)用程序代理對(duì)象的一個(gè)方法。

Of these two techniques, the first is more common given that many menu commands act on the current document or its contents, which are part of the responder chain. The second technique is used primarily to handle commands that are global to the app, such as displaying preferences or creating a new document. It is possible for a custom application object or its delegate to dispatch events to documents, but doing so is generally more cumbersome and prone to errors. In addition to implementing action methods to respond to your menu commands, you must also implement the methods of theNSMenuValidation protocol to enable the menu items for those commands.

這兩種技術(shù)中,第一種通常用于針對(duì)作為響應(yīng)者鏈的一部分的當(dāng)前文檔或其內(nèi)容的目錄命令。第二種技術(shù)主要用于處理應(yīng)用全局性的命令,比如顯示偏好或創(chuàng)建一個(gè)新文檔。自定義應(yīng)用程序?qū)ο蠡蚱浯韺⑹录峙傻轿臋n是可能的,但這樣做效率低下且易出錯(cuò)。除了實(shí)現(xiàn)操作方法來(lái)響應(yīng)菜單命令之外,還必須實(shí)現(xiàn)NSMenuValidation協(xié)議的方法,來(lái)為這些命令啟用菜單項(xiàng)。

Step-by-step instructions for connecting menu items to action methods in your code are given in Designing User Interfaces in Xcode. For more information about menu validation and other menu topics, seeApplication Menu and Pop-up List Programming Topics.

Designing User Interfaces in Xcode給出了關(guān)于將菜單項(xiàng)連接到代碼中的操作方法的步驟說(shuō)明。關(guān)于目錄驗(yàn)證和其它目錄話(huà)題,參考Application Menu and Pop-up List Programming Topics。

原文摘自蘋(píng)果官網(wǎng),譯文為原創(chuàng),請(qǐng)勿轉(zhuǎn)載。水平有限,譯文有錯(cuò)誤、疏漏之處,敬請(qǐng)指正。知識(shí)有價(jià),感謝您支持原創(chuàng),微信掃碼贊助:郵箱:johnbob2014@icloud.com微信公眾號(hào)CocoaLover,掃碼關(guān)注:


發(fā)表評(píng)論 共有條評(píng)論
用戶(hù)名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 仙居县| 哈密市| 江永县| 米易县| 读书| 达拉特旗| 乃东县| 三江| 宁阳县| 南澳县| 舒兰市| 甘谷县| 商丘市| 榆社县| 太湖县| 古交市| 嘉定区| 分宜县| 关岭| 亚东县| 琼结县| 荆州市| 亳州市| 琼海市| 梅河口市| 外汇| 菏泽市| 雅安市| 新源县| 肇东市| 江津市| 盘山县| 遂溪县| 鹿邑县| 定远县| 比如县| 公主岭市| 北流市| 民县| 南皮县| 义马市|