Integrate Your Code with the Frameworks---整合你的代碼和框架

Integrate Your Code with the Frameworks

When you develop an app for OS X or iOS, you won’t be on your own. You’ll be drawing on the work done by Apple and others, on the classes they’ve developed and collected in Objective-C frameworks. A framework is a class library that can be shared by multiple processes at runtime; it includes the resources that support software development with that library. The Cocoa and Cocoa Touch frameworks give you a set of interdependent classes that work together to structure a part—often a substantial part—of your app.html

當你開發一個OS X 或 iOS 應用程序時,你不會就靠你本身。 你將藉助Apple 和 其它人所製做的各類類,這些類被收集在Objective-C框架裏。 一個框架是一個類庫,該類庫能在runtime同時被多個進程所共享;它包含了支持用該庫進行軟件開發的各類資源。 Cocoa 和 Cocoa Touch框架給你提供了一組相互依存的類,它們一塊兒工做構成你應用程序的一部分--每每是一個主要部分。編程

With a library of C functions, you can more or less pick and choose which functions to use and when to call them, depending on the program you’re trying to write. A framework, on the other hand, imposes a design on your program, or at least on a certain problem space your program is trying to address. When using an object-oriented framework, you can call methods of the framework’s classes to do much of the work of the program, just as in a procedural program. But you’ll also need to customize the generic framework behavior and adapt it to your needs by implementing methods that the framework will invoke at the appropriate time. These methods are hooks that introduce your code into the structure imposed by the framework, augmenting it with the behavior that characterizes your program.windows

 使用一個C函數庫,你能夠或多或少挑選幾個函數使用,當你調用它們時,取決於你想編寫的程序。另外一方面,框架決定了你程序的一個設計,或者至少決定了一個你程序想要處理的目標問題空間。當你使用一個面向對象的框架時,你能夠調用該框架裏各類類的各類方法來完成程序裏的不少動做,就像一個程序的程序。可是你也將須要定製該框架的經過框架行爲,而後經過在合適的時候實現框架中的各類方法以適應你的需求。這些方法把你的代碼引入(introduce)被框架所規定(imposed)的結構中,和框架行爲一塊兒描述你的程序。設計模式

The following sections explore this relationship between framework code and application code.安全

如下章節探索框架代碼和應用程序代碼之間的關係。網絡

Apps Are Driven by Events

應用程序是由事件驅動的

You can gain some insight into the relationship between your code and framework code by considering what takes place when an application launches. Basically, the app sets up a core group of objects and turns control over to those objects. More and more objects will be created as the program runs, but at the outset all that’s required is enough structure—that is, enough of the core object network—to handle the initial tasks. There are two primary tasks:架構

經過考慮當一個應用程序啓動時發生了什麼,能夠洞察一些你的代碼跟框架代碼之間的關係。基本上,應用程序啓動對象的核心組(core group), 而後把控制權移交給這些對象。 當程序運行時,愈來愈多的對象將被建立, 可是在一開始全部的需求是足夠的結構---就是足夠的核心對象網絡---用來處理初始化任務。 它有兩項主要任務:app

  • Draw the app’s initial user interface.框架

    繪製應用程序初始用戶界面less

  • Handle the events received when the user interacts with that user interface.

    當用戶跟那個用戶界面交互時,處理接收到的各類事件

After the initial user interface is on the screen, the app is driven by external events, the most important of which are those originated by users (for example, by clicking a button). The operating system reports such events, along with information about them, to the app. The app, consisting of both your code and that of the frameworks, handles the events and updates the user interface accordingly.

當初始用戶界面顯示在屏幕上之後, 應用程序由外部事件驅動, 這些外部事件都源於用戶(好比,點擊按鈕)。操做系統嚮應用程序報告這些事件,以及跟它們有關的各類信息。 由你的代碼以及框架代碼組成的應用程序處理這些事件,從而更新用戶界面。

An app gets an event and responds to it, often by drawing a part of the user interface. It then waits for the next event. It keeps getting events, one after another, as long as the user or some other source (such as a timer) initiates them. From the time an app is launched to the time it terminates, almost everything it does is driven by user actions in the form of events.

應用程序獲取一個事件並對它作出迴應,一般是經過繪製用戶界面的一部分。 而後它又等待下個事件。 它一個接着一個的獲取事件,只要用戶或者一些別的資源(好比一個定時器)觸發它們。應用程序從啓動到中止,它作的全部事情幾乎都是由用戶動做以事件的形式驅動的。

The mechanism for getting and responding to events is the main event loop. In the group of core objects of an app, one object, the global app object, is responsible for managing the main event loop; it gets an event, dispatches the event to the object or objects that can best handle it, and then gets the next event. This figure illustrates the main event loop for Cocoa apps in OS X.

獲取並響應各類事件的機制是主要事件循環。 在應用程序的核心對象組裏,有一個全局應用對象負責該主要事件循環;它獲取一個事件 ,並把它分發給一個或一個能對它作出最好處理的對象,而後獲取下一個事件。 下圖顯示了OS X 中 Cocoa 應用程序的主要事件循環。

The main event loop (Mac OS X)

Using an Object-Oriented Framework

使用一個面向對象框架

The Cocoa and Cocoa Touch frameworks are more than a grab bag of individual classes that offer their services. They contain object-oriented frameworks, which are collections of classes that structure a problem space and present an integrated solution to it. Instead of providing discrete services that you can use as needed (as with function libraries), a framework maps out and implements an entire application structure that your own code must adapt to. Because this application structure is generic, you can specialize it to meet the requirements of your particular app. Rather than design an app that you plug library functions into, you plug the code for your app code into the design provided by the framework.

Cocoa 和 Cocoa Touch 框架擁有各類各樣的獨特類來提供它們的服務。 它們包含各類面向對象的框架,框架收集了解決一個問題空間的各類類,並提供了一個完整的解決方法。框架設計並實現了一整個應用程序結構,而不是提供當你須要的可以使用的各類鬆散服務(好比 函數庫),你編寫的代碼必須可以適應這個結構。由於這個應用程序結構是通用的,因此你能夠專一於讓它符合你的特殊應用程序的需求。你往框架提供的設計裏插入你的應用程序代碼,而不是設計一個你向它插入庫函數的應用程序。

To use a framework, you must accept the application structure it defines and then employ and customize as many of its classes as necessary to mold your particular app to that structure. The classes of a framework are mutually dependent and come as a group, not individually. At first glance, the need to adapt your code to a framework’s structure for apps might seem restrictive. But the reality is quite the opposite. A framework offers you many ways in which you can alter and extend its generic behavior. It simply requires you to accept that all apps behave in the same fundamental ways because they are all based on the same structure. In a broad metaphorical sense, an Objective-C framework is like the framework of a house, and your app code is like the doors, windows, siding, and other elements that make the house unique.

想要使用一個框架,你必須結構它定義的應用程序結構,而後僱傭並定製(customize)儘量多的框架類來往那個結構裏鑄造(mold)你的特殊應用程序。 一個框架裏的全部類都是相互依賴並做爲一個羣體出現,它們不是相互獨立的。乍一看,應用程序中讓你的代碼適應一個框架的結構多是受限制的。 可是現實中它是徹底相反的。 框架提供了不少方法讓你轉換和擴展它的通用行爲。 它只簡單要求你以相同的基礎方式接受全部的應用程序行爲,由於它們都基於相同的結構。用比喻來講,一個Objective-C框架就像一個房子的框架, 而你的代碼就像門, 窗口,滑槽,以及讓這房子變得獨特的其餘各類元素。

image: ../Art/house_framework.png

From the perspective of using a framework and integrating your code with it, there are two general kinds of classes.

透過使用一個框架並集成你的代碼,有兩種基本類型的類(classes)。

  • Off the shelf. Some classes define off-the-shelf objects—that is, objects that are ready to be used. You simply create instances of the class and use the instances as needed.

    Off the shelf. 一些類定義off-the-shelf 對象---就是,即將被使用的對象。 你簡單的建立類的各類實例並在須要的時候使用它們

  • Generic. With generic framework classes, you can—and must in some circumstances—create subclasses of them and override the implementations of certain methods. By subclassing them, you introduce your code into the application structure. The framework invokes the methods of your subclass at the appropriate moments.

    通用類。對於通用框架的類,你能夠--在一些狀況下必須--建立它們的子類,並重寫一些特定方法的實現方法。經過稱爲它們的子類,你把你本身的代碼加入到應用程序結構中。 框架在合適的時候調用你子類的各類方法。

Subclassing a generic framework class is a major technique for integrating your program-specific code into the structure provided by the frameworks. But it is not the only technique, and in many cases is not the preferred technique. As you’ll learn in a later article, the Cocoa and Cocoa Touch frameworks also include architectures and mechanisms, all based on design patterns, that enable greater cooperation and coordination between framework objects and your custom objects.

子類化一個通用框架類是整合(integrating)你的程序特定代碼到框架結構中的一項主要技術。但不是惟一技術, 並且在一些狀況下着也不是首選(prefered)技術。正如你在稍候的文章中所學,Cocoa 和 Cocoa Touch框架還包含了各類架構(architectures)和機制(mechanisms), 它們都基於各類設計模式,能加強框架對象跟你的自定義對象之間的合做與協調(cooperation and coordination)。

When you make a subclass, you have two basic decisions to make: which class to inherit from (the superclass) and which methods of that class to override. The following sections explore the context for making these decisions.

當你建立一個子類,你須要作兩個基本決定: 從哪一個類上繼承(父類) 以及 重載(override)該類的哪些方法。接下來的章節探索如何作這些決定。

Inheriting from a Cocoa or Cocoa Touch Class

從Cocoa 或 Cocoa Touch 類繼承

A framework such as AppKit defines a structure that, because it is generic, many types of apps can share. Because the structure is generic, it is not surprising that a few framework classes are abstract or intentionally incomplete. Such a class often implements a fair amount of common code, but leaves significant portions of the work either undone or completed in a safe default fashion.

框架好比AppKit定義了一個結構,它能讓不少多種類型的應用程序共享,由於框架是通用的。 正由於結構是通用的,因此有一小部分框架中的類是抽象的或者有意的不完整也不須要驚訝。 這樣的一個類一般常實現了至關數量的通用代碼,可是以安全默認的方式保留了相當重要的一部分工做包括沒作的或者是沒完成的。

A major way to add application-specific behavior to a framework is to create a custom subclass of one of these framework classes. The subclass fills in these gaps in its superclass, supplying the pieces the framework class is missing. An instance of your custom subclass takes its place in the network of objects the framework defines and inherits from the framework the ability to work with other objects. For an app to do anything useful, it must create at least one subclass and possibly many of them.

給一個框架添加應用程序特性行爲的一個主要方法就是建立這些框架類中某個類的的一個自定義子類。子類填補了父類的這些空白,提供了框架類遺失的那些部分。 你所定義(custom)的子類的實例定義在框架定義的對象網絡中,而且從框架繼承了跟其它對象一塊兒工做的能力。 讓一個應用程序作一個有用的事情,它必須至少建立一個子類,也可能須要多個。

The following discussion explores some of the decisions and strategies that go into subclassing and describes some of the general requirements. It does not cover in detail how to make a subclass. 「Defining a Class」 in The Objective-C Programming Language describes that technique.

如下的討論探索一些進入子類的決定(decisions)和策略(strategies),同時描述了一些基本需求。 它沒有覆蓋全部有關如何打造(make)一個子類的細節。Objective-C 編程語言(The Objective-C Programming Language)中描述了"Defining a Class"技術。

When to Make a Subclass

什麼時候打造一個子類

Subclassing is a process of reusing an existing class and specializing it for your needs. Sometimes all a subclass needs to do is override a single inherited method and have the method do something slightly different from the original behavior. Other subclasses might add one or two attributes to their superclass (as instance variables) and then define the methods that access and operate on these attributes, integrating them into the superclass behavior.

子類化(subclassing)是從新使用一個已經存在的類並使它專門符合你的需求的一個過程。 有時一個子類所要作的所有僅僅是重載(override)單個被繼承的方法,並讓該方法作一些跟原始行爲稍微有所區別的事情。 其它子類也許向它們的父類添加一個或2個屬性(做爲實例變量),而後定義訪問和操做這些屬性的方法。

Subclassing starts with identifying the framework class to subclass from. Here are a few considerations to guide you:

子類化從識別子類從哪一個框架類繼承開始。 這裏有一些參考指導:

  • Know the framework. You should become familiar with the purpose and capabilities of each class in the framework. To begin, read the introduction to a framework in the developer library and scan the list of the framework’s classes. Maybe there is a class that already does what you want to do. And if you find a class that does almost what you want to do, you’re in luck. That class is a promising superclass for your custom class.

    瞭解框架。 你應該熟悉框架中每一個類的目標和能力。首先,閱讀在開發庫(developer library)裏的框架說明, 而後瀏覽框架的類列表。 也許你已經找到一個類能完成你想要作的所有事情。若是你找到一個類能完成你想作的絕大多數事情, 你也很幸運。 那個類就有但願是你自定義類的一個父類。

    For example, when you worked through Your First Mac App, you encountered NSTextField and other classes of the AppKit framework. To find out more about these classes, you could do the following:

    舉個例子,當你學習Your First Mac App時,你遇到了NSTextField 類 和 AppKit 框架中的其它類。 想要找出更多關於這些類的內容,你能夠:

    1. In Xcode, choose Window > Organizer.

      在Xcode, 選擇 Windoe > Organizer.

    2. Click the Documentation button in the toolbar.

      點擊 工具欄裏的 Documentation 按鈕

    3. Click the Browse button at the top of the navigation area to begin browsing your installed developer libraries. (This button looks like an eye.)

      點擊navigation area(導航區)的 瀏覽按鈕,開始瀏覽你已經下載的開發者庫。(該按鈕看起來像一隻眼睛)。

    4. Click the most recent OS X core library (you might have to log into Apple Developer first).

      The OS X Developer Library opens in the content area.

      點擊 最新的 OS X 核心庫(core library---你可能須要首先登錄Apple Developer(蘋果開發者))。

    5. In the Documents filter field above the list of documents in the documentation area, type 「AppKit Framework Reference」.

      The filtered list now shows only the name of the entered document.

      在文檔區的列表上面的文檔過濾項,輸入「AppKit Framework Reference」。如今過濾列表僅顯示跟輸入內容相關的文檔。

    6. Click AppKit Framework Reference to open a page that lists all the classes and protocols of AppKit.

      點擊AppKit Framework Reference 打開列出AppKit框架的全部類和協議的頁面。

    Read the introduction and click a listed class or protocol to learn more about it.

    閱讀介紹,點擊列表中的類或協議學習它的更多內容。

  • Be very clear about what your app is supposed to do. This advice applies to the app as a whole and to specific parts of the app. Some framework architectures impose their own subclassing requirements. For example, if your app is document-based, you must subclass an abstract document class.

    弄清楚你的應用程序想要作什麼。 該建議適用於整個應用程序,也適用於應用程序的一個特定部分。 一些框架結構額外強加一些它們本身的子類化需求。 好比,若是你的應用程序是基於文檔的,你必須子類化一個抽象文檔類。

  • Define the role played by an instance of your subclass. In app development for OS X and iOS, the Model-View-Control design pattern is used to assign roles to objects. View objects appear on the user interface; model objects hold application data (and implement the algorithms that act on that data); controller objects mediate between view and model objects. Knowing what role an object plays can narrow the decision of which superclass to use. For example, if you want to do custom drawing in an OS X app, you might have to subclassNSView, the base view class in the AppKit framework.

    定義子類的一個實例要表演的角色。 在 OS X 和 iOS開發中,模型-視圖-控制器(M-V-C)設計模式被用來給對象們分配角色;控制器對象在視圖和模型對象之間作調解。 瞭解一個對象扮演什麼角色能讓選擇哪一個父類變得容易。好比,若是你想在一個OS X 應用程序裏自定義繪圖,你可能不得不成爲NSView的子類,NSView 是AppKit 框架裏的基本視圖類。

Despite its importance in programming for OS X and iOS, subclassing is sometimes not the best way to solve a problem. If you just want to add a few convenience methods to a class, you might create a category instead of a subclass. Or, to inject application-specific behavior, you could employ one of the many other resources of the frameworks based on design patterns—for example, delegation. (These patterns are described in the Design Patterns article Streamline Your App with Design Patterns.) And bear in mind that some framework classes are not meant to be subclassed. The reference documentation tells you whether a framework class is meant to be subclassed.

儘管子類化在OS X 和 iOS編程裏很重要,可是有時它卻不是解決一個問題的最佳方法。 若是你只是想給類添加一些方便的方法, 你可能須要建立一個類別(category)代替一個子類。或者,想注入應用程序特定行爲,你能夠僱傭那些基於設計模式的框架中某個框架中的其它資源來完成---好比,delegation。(這些設計模式在Streamline Your App with Design Patterns裏描述。) 另外,請記住有一些框架中的類是不容許被子類化的。 引用文檔會告訴你該框架類可否被子類化。

Overriding a Method

重載一個方法

It’s possible to create a subclass that doesn’t reimplement any superclass methods; for example, the subclass might add additional state and define new methods that access that state and call methods of the superclass. However, for some subclasses the primary task is implementing a specific set of methods declared by a superclass (or in a protocol adopted by a superclass). Reimplementing an inherited method is known as overriding that method.

建立一個子類可是不實現任何父類的方法也是可能的;好比,子類可能添加了額外的狀態,並定義了新方法來訪問該狀態,同時調用父類的各類方法。 然而,對於一些子類來講主要任務就是實現一個父類的特定方法集(或者在一個父類採用的一個協議裏)。從新實現一個繼承的方法被稱爲重載。

Most methods defined in a framework class are fully implemented; they exist so that you can invoke them to obtain the services the class provides. You rarely need to override such methods and shouldn’t attempt to. Other framework methods can be overridden, but there’s seldom a reason to do so.

一個框架裏定義的絕大多數方法都是徹底被實現的;因此你能夠調用它們得到類提供的各類服務。 你不多須要去重載這樣的方法,也不該該去嘗試。 其它框架方法能被重載,可是也不多有理由須要這麼作。

Some framework methods, however, are intended to be overridden; they exist to let you add program-specific behavior to the framework. Often the method, as implemented by the framework, does little or nothing that’s of value to your app. To give content to these kinds of methods, an app must implement its own version. The framework calls these methods at appropriate junctures in an app’s runtime life.

然而,一些框架方法是打算被重載的;它們存在就是想讓你往框架裏添加程序特定的行爲。這些方法一般正如框架所實現的那樣,對你應用程序所要完成的工做來講只作了一點或根本沒作。一個應用程序必須實現它本身的方法版本才能往這些方法添加內容。在應用程序runtime生命週期中, 框架在適當的時候調用這些方法。

Invoke or Override?

The framework methods you override in a subclass won’t generally be the methods that you’ll invoke yourself, at least not directly. You simply reimplement the method and leave the rest up to the framework. In fact, the more likely you are to write an application-specific version of a method, the less likely you are to invoke it in your own code. In a general sense, a framework class declares public methods so that you, the developer, can do one of two things with them:

你在一個子類裏從框架方法那重載的方法通常不是所有調用你自身的實現,至少不會直接調用你自身的實現。你簡單從新實現該方法,把剩下部分留給框架實現。 事實上, 你可能更多的是實現一個方法的應用程序特定版本, 從你本身的代碼裏調用它可能更少。 通常來講,框架類定義公共方法,這樣你或者說是開發者就能用它們完成一件或兩件事情:

  • Invoke them to use the services the class provides.

    調用它們使用類提供的各類服務

  • Override them to introduce your own code into the program model defined by the framework.

    重載它們來往框架定義的程序模型里加入你本身的代碼

Sometimes a method falls into both these categories; it renders a valuable service upon invocation, and it can be strategically overridden. But in most cases, if a method is one that you can invoke, it’s fully defined by the framework and doesn’t need to be redefined in your code. If the method is one that you need to reimplement in a subclass, the framework has a particular job for it to do and so will invoke the method itself at the appropriate times. This figure illustrates the two general types of framework methods.

有時一個方法會同時屬於這些類別(categories);它能被調用得到有價值的服務,也能被戰略性的重載。可是在大多數狀況下,若是一個方法能被你調用,它就是被框架徹底定義,並不須要在你的代碼裏被從新定義。 若是一個方法是須要你在一個子類裏從新實現,則框架作了該方法的部分工做,它將在適當的時候自動調用該方法。下圖顯示了框架方法的2種基本類型。

 

Invoking a framework method that messages an overridden method

In this figure, a hypothetical method of your custom class (myMethodcalls the setNeedsDisplay method, which is implemented by a framework. The framework does some work to set up the environment for drawing and then calls the framework-declared method drawRect:, which is overridden by the custom class to do the actual drawing.

在上圖,假設一個自定義類(myMethod)的一個方法調用了setNeedsDisplay方法, 該方法由一個框架定義。框架作了一些工做---創建了繪圖的環境,而後調用框架聲明的方法drawRect:,該方法被自定義類重載來完成實際繪圖。

Overriding a method does not have to be a formidable task. You can often make significant change in superclass behavior by a careful reimplementation of the method that entails no more than one or two lines of code.

重載一個方法不必定是一個艱鉅的任務。 你經常能夠在父類行爲裏作重大變化,只需不超過一或兩行代碼對該方法作一個仔細的從新實現。

Calling the Superclass Implementation

調用父類實現

When you override a framework method, you have to decide whether to replace the behavior of the inherited method or extend or supplement that behavior. If you want to replace the existing behavior, simply provide your own implementation of the method; if you want to extend that behavior, call the superclass implementation and provide your own code.

當你重載一個框架方法,你必須決定是否要替換被繼承的方法,或者擴展或者補充那個行爲。 若是你想要替換存在的行爲,你只要簡單的提供你本身對於那個方法的實現;若是你想擴展它,你須要調用父類實現並提供你本身的代碼。

You call the superclass implementation by sending the same message that invoked the method to super. By sending the message to super, you 「plug in」 the superclass’s code for that method into your reimplementation at the point of invocation. For example, let’s say that a hypothetical Celebrate class defines a method named performFireworks. After the framework draws and animates fireworks in a view, you want to display a banner in the view. The following figure illustrates how calling super works in this case:

使用關鍵字super給父類的方法實現發送一個消息就能夠調用父類方法的實現。 經過給super發送消息,你在從新實現的代碼頂部加入了父類的實現代碼。 好比,讓咱們看看一個虛擬類Celebrate類定義了一個方法performFireworks. 當框架在視圖上繪製和播放完煙火動畫以後,你想要在視圖上顯示一個banner。下圖顯示瞭如何調用super,讓其調用父類的實現代碼。

image: ../Art/calling_super_2x.png

Thus, the decision to call super is based on how you intend to reimplement a method:

因此,調用super這個決定是基於你如何打算從新實現一個方法的基礎上的:

  • If you intend to supplement the behavior of the superclass implementation, call super.

     若是你打算補充父類的實現行爲,調用super。

  • If you intend to replace the behavior of the superclass implementation, don’t call super.

     若是你打算替換父類實現的行爲,別調用super。

If you supplement superclass behavior, another important consideration is when to invoke the superclass implementation of a method. You might want the superclass code to do its thing before your code is executed, or vice versa.

相關文章
相關標籤/搜索