Acquire Basic Programming Skills

Acquire Basic Programming Skills

掌握基础编程技巧

The Foundation framework, as its name suggests, is the foundational toolkit for all programming for both iOS and Mac OS X. You need to become familiar with this toolkit to be a successful developer for these platforms.

The Foundation framework,就像他的字面意思解释的那样,是所有IOS和MAC OS X程序的基础工具箱。为了成为这些平台的成功开发者,你需要变得对这个工具箱很熟悉。

Foundation defines dozens of classes and protocols for a variety of purposes, but three categories of classes and protocols stand out as particularly fundamental:

为了实现各种各样的用途Foundation定义了许多类和协议,但有三个范畴的类和协议因为其特别重要尤其突出:

  • The root class and related protocols. The root class, NSObject, along with a protocol of the same name, specifies the basic interface and behavior of all Objective-C objects. There are also protocols a class can adopt so clients can copy instances of the class and encode their state.

  • 根类及相关协议。根类NSObject,和一个同名的协议一起,共同规定所有Objective-C项目的界面和性能。当然也有一些可以被某一个类使用的协议,然后用户可以拷贝这个类的一些实例再编码他们自己的程序。

  • Value classes. A value class generates an instance (called a value object) that is an object-oriented wrapper for a primitive data type such as a string, a number, a date, or binary data.

  • 值类。值类创造实例(被称为值对象)——一个原始数据类型(诸如字符串,数字,日期或者二进制数据)的面向对象包装器。

  • Collection classes. An instance of a collection class (called a collection) manages a group of objects. What distinguishes a particular type of collection is how it lets you access the objects it contains. Often the items in a collection are value objects.

  • 集合类。一个集合类的实例(被称为集合)管理一组对象。辨别一个特定类集合的是它让你使用它所包含的对象的方法。通常集合里的项目都是值对象。

Collections and value objects are extremely important in Objective-C programming because you frequently find them as the parameters and return values of methods.

集合对象和值对象在Objective-C程序中是相当重要的,因为你会频繁的在参数和方法的返回值中找到它们。

 

The Root Class and Objective-C Objects

根类和Objective-C对象


In a class hierarchy, a root class inherits from no other class and all other classes in the hierarchy ultimately inherit from it.NSObject is the root class of Objective-C class hierarchies. From NSObject, other classes inherit a basic interface to the Objective-C runtime system. And from NSObject, the instances of these classes derive their fundamental nature as Objective-C objects.

在类继承体系中,根类不从任何其他类继承而体系中其他所有类源头上都是从根类继承的。NSObject是Objective-C类继承体系的根类。其它类从NSObject继承基础界面然后运用到Objective-C运行时系统。这些类的实例也从NSObject得到它们基本的属性,成为OBjective-C对象。

But by itself, an NSObject instance cannot do anything useful beyond being a simple object. To add any properties and logic specific to your program, you must create one or more classes inheriting from NSObject or from any other class that directly or indirectly inherits from NSObject.

但如果仅靠自己,一个NSObject实例除了做一个简单的对像外什么有意义的事情也做不了。为了给你的程序增加一些性能和逻辑特效,你必须创建一个或者多个类,它们继承NSObject或者其它直接或是间接继承NSObject的类。

NSObject adopts the NSObject protocol, which declares additional methods common to the interfaces of all objects. In addition, NSObject.h (the header file containing the class definition of NSObject) includes the NSCopying,NSMutableCopying, and NSCoding protocols. When a class adopts these protocols, it augments the basic object behaviors with object-copying and object-encoding capabilities. Model classes—those classes whose instances encapsulate application data and manage that data—frequently adopt the object-copying and object-encoding protocols.

NSObject采纳NSObject协议,这个协议声明增加的方法为所有对象界面共用。另外,NSObject.h(包含NSObject类定义的头文件)包含NSCopying,NSMutableCopyingNSCoding协议。当一个类采纳这些协议,他会因为对象拷贝和对象编码能力而增强基本的对象性能。模型类——那些类的实例囊括应用数据,管理频繁采用对象拷贝和对象编码协议的数据。

The NSObject class and related protocols define methods for creating objects, for navigating the inheritance chain, for interrogating objects about their characteristics and capabilities, for comparing objects, and for copying and encoding objects. Much of the remainder of this article describes the basic requirements for most of these tasks.

NSObject类和与之相关的协议定义了方法来创造对象,操纵继承链,审查对象的特性和能力,比较对象以及复制和编码对象。这篇文章剩下的大部分也是在描述上述大部分工作的基本要求。

Create Objects

创造对象

You usually create an object by allocating it and then initializing it. Although these are two discrete steps, they are closely linked. Many classes also let you create an object by calling a class factory method.

通常创造一个对象的方法是给它分配内存然后初始化它。尽管这是两个不相关的步骤,但它们紧紧地连在一起。很多类也会使用调用类工厂方法来创建对象。

Create an Object by Allocating and Initializing It

用分配和初始化的方法创建对象

To allocate an object, you send an alloc message to the object’s class and get back a “raw” (uninitialized) instance of the class. When you allocate an object, the Objective-C runtime allocates enough memory for the object from application virtual memory. In addition to allocating memory, allocation does a few other things, such as setting all instance variables to zero.

为了分配一个对象,你需要发送一个分配的信息给对象的类然后得到该类的一个原始的(未初始化的)实例。当你给一个对象分配内存的时候,Objective-C运行时刻会从应用的实际内存中为该对象分配足够的内存。除了分配内存之外,分配过程还做了一些其他事情,比如把所有的实例变量设置为0。

Right after allocating the raw instance, you must initialize it. Initialization sets an object’s initial state—that is, its instance variables and properties—to reasonable values and then returns the object. The purpose of initialization is to return a usable object.

在分配原始实例之后,你必须初始化它。初始化给对象的初始状态(即他的实例变量和性能)设置一个合理的值然后返回该对象。初始化的目的就是返回一个可用的对象。

In the frameworks you will find many methods called initializers that initialize objects, but they all have similarities in their form. Initializers are instance methods that begin with init and return an object of type id. The root class, NSObject, declares the init method, which all other classes inherit. Other classes may declare their own initializers, each with its own keywords and parameter types. For example, the NSURL class declares the following initializer:

在frameworks中你可以找到很多被叫做初始化程序的,用来初始化对象的方法,但它们的形式中都有类似的部分。初始化程序是以init开始,返回id类型对象的实例方法。根类NSObject声明了init方法,其他所有类从NSObject继承此方法。其它的类也可以声明他们自己的初始化程序,使用它们自己的关键字和参数类型。例如,NSURL类声明了下面的初始化程序:

- (id)initFileURLWithPath:(NSString *)path isDirectory:(BOOL)isDir

When you allocate and initialize an object, nest the allocation call inside the initialization call. Using the above initializer as an example:

当你分配然后初始化一个对象的时候,在初始化指令中添加分配指令。使用上面这个初始化程序的例子:

NSURL *aURL = [[NSURL alloc] initFileURLWithPath:NSTemporaryDirectory() isDir:YES];

As a safe programming practice, you can test the returned object to verify that the object was created. If something happens during either stage that prevents the object’s creation, the initializer returns nil. Although Objective-C lets you send a message to nil without negative consequences (for example, thrown exceptions), your code will not work as expected because no method is called. You should not use the instance returned by alloc instead of the one returned by the initializer.

作为一个安全的编程练习,你可以测试返回对象来核实对象是否被创建。如果在任一阶段发生了一些阻止对象创建的事情,初始化程序将返回nil。虽然Objective-C允许向nil传送信息,也不会有消极效果(比如抛出异常),但代码不会像预期一样执行,因为没有方法被调用。你应该使用从初始化程序返回的实例而不是从alloc返回的。

Create an Object by Calling a Class Factory Method

调用类工厂方法创建对象

You can also create an object by calling a class factory method: a class method whose purpose is to allocate, initialize, and return an instance of itself. Class factory methods are conveniences because they permit you to create an object in one step rather than two. They are of the form:

你也可以调用类工厂方法(一个目的是分配,初始化然后返回自身实例的类方法)来创建对象。类工厂方法使用方便,因为它允许你只用一步而不是两步来创建对象。它们的形式是这样的:

  • + (type)className... (where className excludes any prefix)

Classes of an Objective-C framework sometimes define class factory methods that typically correspond to initializers of the class. For example, NSString declares the following two methods:

一个Objective-C framework的类有时会定义一个与该类的初始化程序很类似的类工厂方法。例如,NSString声明了下面两个方法:

- (id)initWithFormat:(NSString *)format, ...;
+ (id)stringWithFormat:(NSString *)format, …;

Here is an example of how you might use this class factory of NSString:

下面是一个你可以怎样使用NSString的类工厂的例子:

NSString *myString = [NSString stringWithFormat:@"Customer: %@", self.record.customerName];

Thinking in Terms of Objects

考虑对象

At runtime, an app is a network of cooperating objects; these objects communicate with each other to get the work of the app done. Each object plays a role, has at least one responsibility, and is connected to at least one other object. (An object in isolation is of little value.) As illustrated in the figure below, the objects in a network include both framework objects and application objects. Application objects are instances of a custom subclass, usually of a framework superclass. An object network is commonly known as an object graph.

在运行时刻,应用程序就是若干相互协作的对象构成的网络;这些对象相互联系,共同完成应用的程序执行。每一个对象扮演一个角色,承担至少一个责任,至少与一个其它对象相连接。(隔离的对象是没有多大价值的)如下图所示,网络中的对象包括集合对象和应用对象。应用对象是自定义子类(通常是一个集合超类)的实例。一个对象网络通常被成为对象图表。

You establish these connections, or relationships, between objects through references. There are many language forms of references, among them instance variables, global variables, and even (within a limited scope) local variables. Relationships can be one-to-one or one-to-many and can express notions of ownership or parent-child correspondence. They are a means for one object to access, communicate with, or control other objects. A referenced object becomes a natural receiver of messages.

通过引用你可以建立对象之间的联系或者关系。有很多引用语言的形式,包括实例变量,全局变量以及(在有限范围内)局部变量。关系可以是一对一或者一对多,可以陈述所有权的概念以及父-子类间的相似处。那是一种可以让一个对象接近,联系,或者控制其它对象的方法。一个引用对象变成一个自然的信息接收器。

Messages between objects in an app are critical to the functional coherence of the app. In a way similar to a musician in an orchestra, each object in an app has a role, a limited set of behaviors it contributes to the app. An object might display an oval surface that responds to taps, or it might manage a collection of data-bearing objects, or it might coordinate the major events in the life of the app. But for its contributions to be realized, it must be able to communicate them to other objects. It must be able to send messages to other objects in the app or be able to receive messages from other objects.

应用程序中对象之间的信息传递对应用程序的功能连贯性来说是至关重要的。类似于管弦乐队的一个音乐家,每一个应用程序的对象承担一些责任,实现应用程序的一部分功能。对象也许表现得像是一个能够响应点击的椭圆形表面,也许是若干含数据对象的集合的管理者,也许是应用程序执行过程中主要事件的协调者。但要想自身的功能被实现,它们必须能够把自己和其它对象联系起来。他们也必须能够把信息发送给应用程序的其它对象或者从其它对象接收信息。

With strongly coupled objects—objects connected through direct references—sending messages is an easy matter. But for objects that are loosely coupled—that is, objects far apart in the object graph—an app has to look for some other communication approach. The Cocoa and Cocoa Touch frameworks feature many mechanisms and techniques enabling communication between loosely coupled objects (as illustrated in the figure below). These mechanisms and techniques, all based on design patterns (which you will learn more about later), make it possible to efficiently construct robust and extensible apps.

在紧密耦合的对象(通过直接引用联系起来的对象)间发送信息是一件很简单的事情。但如果是一些松散耦合的对象(即对象在对象图表中的距离很远),应用程序就不得不寻找一些其它的联系方法了。Cocoa和Cocoa Touch frameworks采用了许多机制与技术使松散耦合对象之间的联系成为可能(如下图所示)。这些机制和技术都是建立在设计模式(后面你将会学到更多关于它的知识)基础上的,它们使得高效地建立强大可扩展的应用程序成为可能。

Manage the Object Graph to Avoid Memory Leaks

通过管理对象图来避免内存泄漏

The objects in an Objective-C program compose an object graph: a network of objects formed by each object’s relationships with—or references to—other objects. The references an object has are either one-to-one or (via collection objects) one-to-many. The object graph is important because it is a factor in the longevity of objects. The compiler examines the strength of references in an object graph and adds retain and release messages where appropriate.

一个Objective-C程序里的所有对象构成了一个对象图:每一个对象与其它对象的联系或者引用构成了一张对象网络。引用可能是一对一的,也可能是一对多的(通过集合对象)。对象图很重要,因为它是对象寿命的一个要素。编译器会审查对象图中引用的健壮度,然后在合适的地方加上retain和release信息。

You form references between objects through basic C and Objective-C constructs such as global variables, instance variables, and local variables. Each of these constructs carries with it an implied scope; for example, the scope of an object referenced by a local variable is the functional block in which it is declared. Just as importantly, references between objects are either strong or weak. A strong reference indicates ownership; the referring object owns the referenced object. A weak reference implies that the referring object does not own the referenced object. The lifetime of an object is determined by how many strong references there are to it. An object is not freed as long as there is a strong reference to it.

在基础C和Objective-C的架构下你可以建立对象(比如全局变量,实例变量,局部变量)之间的引用。每一个架构都自带了一个隐藏职能。例如,一个被局部变量引用的对象,是其声明位置的功能模块。同等重要的是,对象之间的引用有强有弱。强引用意味着所有权;指对象拥有引用对象。弱引用则暗示指对象并不拥有引用对象。一个对象的使用期决定于有多少强引用指向它。对象在强引用指向它的时候不会被释放。

References in Objective-C are strong by default. Usually this is a good thing, enabling the compiler to manage the runtime life of objects so that objects are not freed while you’re using them. However, if you’re not careful, strong references between objects can form an unbroken chain of references, as illustrated on the left in the diagram below. With such an unbroken chain, it’s possible that the runtime will free none of the objects because there is a strong reference to each of them. Consequently, a strong reference cycle can cause your program to leak memory.

默认状态下Objective-C的引用是很强的。授权编译器管理对象的运行时过程这样对象就不能在我们使用它们的时候被释放,通常情况下这是个好事情。可是,如果你不够小心,对象之间的强引用会像下图左边所示的那样,形成一个完整的引用链。在这样一个完整链中,运行时刻可能一个对象都不会释放,因为每一个对象都有一个强引用指向他。所以,一个强引用圈会是你的程序内存泄漏。

For the objects in the figure, if you break the reference between A and B, then the subgraph consisting of B, C, D, and E lives on “forever” because these objects are bound together by a cycle of strong references. By introducing a weak reference from E to B, you break this strong reference cycle.

就这张图中的对象而言,如果你解除A和B之间的引用,由B、C、D、E构成的子链也会永远存在,因为这些对象被一个强引用圈绑在了一起。如果你在E到B引进一个弱引用,这个强引用圈就被你解除了。

Thus the fix for strong reference cycles is the judicious use of weak references. The runtime keeps track of weak references to an object. Once there are no strong references to an object, it frees that object and sets any weak references to the object to nil. For variables (global, instance, and local), use the __weak qualifier just before the variable name to mark the reference as weak. For properties, use the weak option. You should use weak references for the following kinds of references:

因此我们需要恰当地使用弱引用来对强引用圈做补充。运行时刻会一直跟踪指向对象的弱引用。一旦没有强引用指向一个对象了,它会立即释放那个对象然后把指向那个对象的弱引用设置为nil。如果是变量(全局变量,实例变量,局部变量),通常是在变量名前面加上_weak修饰语来把引用标记为弱引用。如果是属性,通常使用weak选项。另外下面这几种引用你也应该使用弱引用:

  • Delegates

  • 委托代理
    @property(weak) id delegate;
    

    You will learn about delegates and targets in the Design Patterns article “Streamline Your App with Design Patterns.”

  • 你可以从“使用设计模型优化你的应用程序”这篇有关设计模型的文章中学到关于代理和目标的知识。

  • Outlets that are not references to top-level objects

  • 不是指向顶层对象的引用的输出口
    @property(weak) IBOutlet NSString *theName;
    

    An outlet is a connection (or reference) between objects that is archived in a storyboard or nib file and restored when an app loads the storyboard or nib file. An outlet for a top-level object in a storyboard or nib file—typically a window, view, view controller or other controller—should be strong (the default, so unmarked).

  • 输出口是对象之间的联系(或引用),那些对象被存档在故事板或者nib文件中,当应用程序读取故事板或者nib文件时就会被恢复。在故事板或者nib文件中的顶层对象的输出口(通常是窗口,视图,视图控制器或者其他控制器)应该是strong的(默认状态,所以不用标记)。

  • Targets

  • 目标
    (void)setTarget:(id __weak)target
    
  • References to self in blocks

  • 模块中对自身的引用
    __block typeof(self) tmpSelf = self;
    
    [self methodThatTakesABlock:^ {
    
        [tmpSelf doSomething];
    
    }];
    

    A block forms a strong reference to variables it captures. If you use self within a block, the block forms a strong reference to self, so if self also has a strong reference to the block (which it typically does), a strong reference cycle results. To avoid the cycle you need to create a weak (or __block) reference to self outside the block, as in the example above.

  • 一个模块会在它捕捉到的变量上加上一个强引用。如果你在一个模块中使用了self,这个模块就会在self上附加一个强引用,所以如果self对这个模块也有一个强引用(通常如此),那么一个强引用圈就形成了。为了避免这个圈,你应该在模块外创建一个weak (或者 __block)引用并指向self,就像上面的例子一样。

Manage Object Mutability

管理对象的可变性

A mutable object is one whose state you can change after creating the object. You typically make changes through properties or accessor methods. An immutable object is one whose encapsulated state you cannot change after creating the object. The instances you'll create of most classes of the Objective-C frameworks are mutable, yet a few are immutable. Immutable objects provide you with the following benefits:

可变对象的属性在你创建了之后可以被改变。通常会使用属性或者访问方法来改变。而不可变对象的封装属性在它被创建之后不能被改变。你所创建的大部分Objective-C frameworks类的实例是可变的,除了一小部分。不可变对象为你提供了以下好处:

  • An immutable object won’t unexpectedly change in value while you’re using it.

  • 不可变对象的值在你使用的时候不会意外地改变。
  • For many types of objects, application performance is improved if the object is immutable.

  • 对很多类型的对象来说,如果它是不可变的,应用程序的执行将得到改良。

In Objective-C frameworks, the instances of immutable classes usually are ones that encapsulate collections of discrete or buffered values—for example, arrays and strings. These classes usually have mutable variants with “Mutable” in their names. For example, there is the NSString class (immutable) and the NSMutableString class. Note that for some immutable objects that encapsulate discrete values, such as NSNumber or NSDate, it doesn’t make sense to have mutable class variants.

在Objective-C frameworks中,不可变类的实例通常封装了离散或缓冲数值(比如说数组,字符串)的集合。这些类通常都有一些名字中含有“Mutable”的可变变量。比如说NSString类(不可变)和NSMutableString类。需要注意的是,有一些不可变对象比如说 NSNumberNSDate,它们封装了一些离散数值,对它们来说,拥有可变类变量并没有意义。

Use mutable objects instead of the immutable variant when you expect to change an object’s contents incrementally and frequently. If you receive an object from a framework that is typed as an immutable object, respect that return type; don’t attempt to change the object.

当你希望频繁地增加对象的内容的时候,请使用可变对象而不是不可变量。如果你接受到一个来自framework的被类型化为不可变对象的对象,请尊重那个返回类型;不要试图去改变那个对象。

Create and Use Value Objects

创建使用值对象

A value object is an object that encapsulates a primitive value (of a C data type) and provides services related to that value. Value objects represent scalar types in object form. The Foundation framework provides you with the following classes that generate value objects for strings, binary data, dates and times, numbers, and other values:

值对象是包含一个原始值(C数据类型)并提供与那个值相关的服务的对象。值对象在对象形式中扮演标量类型的角色。Foundation framework为你提供了下面这些类,它们为字符串,二进制数据,日期和时间,数字以及其他数值创造值对象。

  • NSString and NSMutableString

  • NSData and NSMutableData

  • NSDate

  • NSNumber

  • NSValue

Value objects are important in your Objective-C programming tasks because of these objects’ ubiquity as the parameters and return values of methods and functions that your application calls. By passing value objects, different parts of a framework or even different frameworks can exchange data. Because value objects represent scalar values, you can use them in collections and wherever else objects are required. But beyond their commonness and consequent necessity, value objects have an advantage over the primitive types they encapsulate: They enable you to perform certain operations on the encapsulated value in a simple yet efficient manner. The NSString class, for example, has methods for searching for and replacing substrings, for writing strings to files or (preferably) URLs, and for constructing file-system paths.

值对象在你的Objective-C程序执行的过程中是很重要的,因为它们普遍存在于应用程序调用的函数和方法的参数和返回值中。通过传递值对象,framework中不同部分甚至不同的 framework都能交换数据。因为值对象扮演的是标量值,你可以在集合中或者其它的任何一个需要使用对象的地方使用它们。但是除了它们的普遍性以及与之伴随的必要性之外,值对象与他们包含的原始类型相比还有一个优点:它们让你能够以一种简单高效的方法对封装值执行一些操作。比如说NSString 类拥有搜索和移动子字符串,在文件或者(更好的)链接上写入字符串以及创造文件系统路径。

In some situations you’ll find it more efficient and straightforward to use primitive types—that is, values typed as int(integer), float, and so on. A primary example of such a situation is computing a value. Consequently, NSNumber andNSValue objects are less common as parameters and return values in framework methods. However, be aware that many of the frameworks declare their own numeric data types and use these types for parameters and return values; examples areNSInteger and CGFloat. You should use these framework-defined types where appropriate because that helps you to abstract your code away from the underlying platform.

在有些情况下你会发现使用原始类型(整型,浮点数等类型的值)会更直接有效。计算数值就是一个基本的例子。因此,在framework方法中,NSNumber和NSValue对象在参数和返回值中并不常见。不管怎样,一定要意识到很多frameworks声明了它们自己的数字数据类型,并把它们运用到参数和返回值中;NSIntegerCGFloat就是很好的例子。记得在适当的时候使用framework自身定义的类型,这样可以帮助你从基础平台中提取你的代码。

The Basics of Using Value Objects

使用值对象的基本操作

The basic pattern for creating a value object is for your code or framework code to create it from data of the primitive type (and then perhaps pass it in a method parameter). In your code, you later access the encapsulated data from the object. The NSNumber class provides the clearest example of this:

创建一个值对象的基本方式是从原始类型数据中为了你的代码或者framework的代码创建它(然后可能在一个方法的参数中传递它)。在你的代码中,你会在后面从这个对象中访问封装的数据。NSNumber提供了这样的一个最清晰的例子:

int n = 5; // Value assigned to primitive type
NSNumber *numberObject = [NSNumber numberWithInt:n]; // Value object created from primitive type
int y = [numberObject intValue]; // Encapsulated value obtained from value object (y == n)

Most “value” classes declare both initializers and class factory methods for creating their instances. Some classes—NSString and NSData in particular—also provide initializers and class factory methods for creating their instances from primitive data stored in local or remote files as well as from data in memory. These classes also provide complementary methods for writing strings and binary data to files or to URL-specified locations. The code in the following example calls the initWithContentsOfURL: method to create an NSData object from the contents of a file located by a URL object; after using the data, the code writes the data object back to the file system:

大部分“值”类为了创建它们的实例都声明了初始化和类工厂方法。有些类——特别是NSString和NSData——为了从被存储在本地或其他地方的文件的原始数据(或者内存中的数据)中创建它们的实例,也提供了初始化和类工厂方法。这些类也提供了互补的方法来把字符串和二进制数据写入文件和链接等指定位置。下面例子中的代码被叫做initWithContentsOfURL:从被一个链接对象定位的文件目录中创建一个NSData对象的方法;当使用完数据后,代码再将数据对象写回文件系统:

NSURL *theURL = // Code that creates a file URL from a string path...
NSData *theData = [[NSData alloc] initWithContentsOfURL:theURL];
// use theData...
[theData writeToURL:theURL atomically:YES];

In addition to creating value objects and letting you access their encapsulated values, most value classes provide methods for simple operations such as object comparison.

除了创建值对象和允许你访问它们的封装数值外,大部分值类还为诸如对象比较的简单操作提供了方法。

Strings

字符串

As a superset of C, Objective-C supports the same conventions for specifying strings as does C. In other words, single characters are enclosed by single quotes and strings of characters are surrounded by double quotes. However, Objective-C frameworks typically do not use C strings. Instead, they use NSString objects.

作为C的扩展集,Objective-C支持和C一样的指定字符串的协议。换句话说,单个字符被附加了单引号而字符串则被附加了双引号。然而,Objective-C frameworks通常不适用C的字符串。它们使用NSString对象作为替代。

You have already created a formatted string when you created the HelloWorld app in Your First iOS App:

你应该已经在你创建Your First iOS App中的HelloWorld应用的时候就已经创建了一个格式化字符串了:

NSString *greeting = [[NSString alloc] initWithFormat:@"Hello, %@!", nameString];

 The NSString classprovides an object wrapper for strings, thereby offering such advantages as built-in memory management for storing arbitrary-length strings, support for different character encodings (particularly Unicode), andprintf-style formatting utilities. Because you commonly use such strings, Objective-C provides a shorthand notation for creating NSString objects from constant values. To use this shorthand, all you have to do is precede a normal, double-quoted string with the @ symbol, as shown in the following examples:

NSString类为字符串提供了一个对象包,从而提供了诸如储存任意长度字符串的内置内存管理,支持不同字符编码(特别是Unicode)以及printf样式的格式化实用程序等优点。因为这些字符串的频繁的被使用,Objective-C为从常值创建NSString对象提供了速记符号。你只需要在一个正常的被加上双引号的字符串前面加上一个@符号来使用这个速记符号,就像下面的例子展示的那样:

// Create the string "My String" plus carriage return.
NSString *myString = @"My String\n";
// Create the formatted string "1 String".
NSString *anotherString = [NSString stringWithFormat:@"%d %@", 1, @"String"];
// Create an Objective-C string from a C string.
NSString *fromCString = [NSString stringWithCString:"A C string" encoding:NSASCIIStringEncoding];

Dates and Times

日期和时间

An NSDate object is different from other kinds of value objects because of the distinctive nature of time as a primitive value. A date object encapsulates the interval, in seconds, from a reference date. That reference date is the first instant of January 1, 2001 GMT.

NSDate对象因为作为原始值的时间所具有的独特性质而和其他种类的值对象是不同的。一个日期对象从引用日期以秒为单位封装时间间隔。这个引用日期是格林尼治标准时间2001年1月1日0时0分0秒。

You can do little with an instance of NSDate just by itself. It does represent a moment in time, but that representation is without the context provided by a calendar, a time zone, and the temporal conventions of a locale. Fortunately, there are Foundation classes representing these conceptual entities:

仅靠NSDate实例本身能实现的功能很少。它确实可以一时间的形式把一个瞬间表示出来,但这种表现是脱离了由日历,时区以及区域的时空公约提供的背景的。好在有一些基础类表现了这些概念性的个体:

  • NSCalendar and NSDateComponents—You can associate the date with a calendar and then derive temporal units from the calendar for the date such as year, month, hour, and day of week. You can also perform calendrical calculations.

  • NSCalendarNSDateComponents——你可以将日期与一个日历相关联,然后从日历中为日期获取时间单位(年,月,小时以及一周的一天)。你也可以执行日历计算。

  • NSTimeZone—When a date and time must reflect the time zone of an area, you can associate a time-zone object with a calendar.

  • NSTimeZone————当一个日期和时间需要反映地区时区的时候,你可以将一个时区对象与日历相关联。

  • NSLocale—A locale object encapsulates cultural and linguistic conventions, including those related to time.

  • NSLocale————一个区域设置对象封装了文化和语言的协议(包括一些和时间相关的)。

The following code snippet illustrates how you can use an NSDate object with these other objects to obtain the information you want (in this case, the current time printed as hours, minutes and seconds). Refer to the numbered list below the code for an explication:

下面的代码片段说明了怎样使用一个NSDate对象和其它对象一起获取想要的信息(在这个例子中是被打印成小时,分钟和秒的当前时刻)。请参考代码下面用来阐释的编号列表:

NSDate *now = [NSDate date]; // 1
NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar]; // 2
[calendar setTimeZone:[NSTimeZone systemTimeZone]]; // 3
NSDateComponents *dc = [calendar components:(NSHourCalendarUnit|NSMinuteCalendarUnit|
    NSSecondCalendarUnit) fromDate:now];  // 4
NSLog(@"The time is %d:%d:%d", [dc hour], [dc minute], [dc second]); // 5
  1. Creates a date object representing the current instant.创建一个日期对象表示当前时刻。

  2. Creates an object representing the Gregorian calendar.创建一个对象表示阳历。

  3. Sets the calendar object with an object representing the time zone specified in System Preferences.用一个表示系统预置里的精确时区的对象来设置这个日历。

  4. Calls the components:fromDate: method on the calendar object, passing in the date object created in step 1. This call returns an object containing the hour, minute, and second components of the date object.对这个日历对象调用 components:fromDate: 方法,传递在第一部中创建的日期对象。这个调用返回一个包含日期对象的小时,分钟,秒几个部分的对象。

  5. Logs the current hour, minute, and second to the console.向主控台输出当前小时,分钟,秒。

Although this example logs the result, the preferred approach for displaying date information in an application’s user interface is to use date formatters (instances of the NSDateFormatter class). You should always use the appropriate class and method for calendrical calculations; don’t hard-code numerical values for units such as minutes, hours, and days.

尽管这个例子输出了结果,但在一个应用程序的用户接口中呈现日期信息的首选方法还是使用数据格式化程序(NSDateFormatter类的实例)。记得永远使用恰当的类和方法来进行日历计算;不要为分钟,小时,天等单位硬编码数字的值。

Create and Use Collections

创建,使用集合

A collection is an object that stores other objects in a certain way and allows clients to access those objects. You often pass collections as parameters of methods and functions, and you often obtain collections as return values of methods and functions. Collections frequently contain value objects, but they can contain any type of object. Most collections have strong references to the objects they contain.

集合是一个以某一种方式储存其它对象并允许客户端访问这些对象的对象。它会经常被当作方法和函数的参数传递,或者被以方法和函数的返回值的形式获得。集合往往包含的是值对象,但是它们也可以包含任一类型的对象。大部分集合对它们包含的对象有很强的引用。

The Foundation framework has several types of collections, but three of them are particularly important in Cocoa and Cocoa Touch programming: arrays, dictionaries, and sets. The classes for these collections come in immutable and mutable variants; mutable collections permit you to add and remove objects, but immutable collections can contain only the objects they were created with. All collections allow you to enumerate their contents—in other words, to examine each of the contained objects in turn.

Foundation framework拥有很多类型的集合,但其中有三个(有序集合,字典和无序集合)在Cocoa和Cocoa Touch编程中尤其重要。这些集合类包含了不可变量和可变量;可变集合允许你增加和移动对象,但不可变集合仅能控制那些和它们一起被创建的对象。所有的集合允许你列举它们的目录——换个说法就是按顺序检查每一个包含的对象。

Different types of collections organize their contained objects in distinctive ways:

不同类型的集合以与众不同的方式组织他们包含的对象:

  • NSArray and NSMutableArray—An array is an ordered collection of objects. You access an object by specifying its position (that is, its index) in the array. The first element in an array is at index 0 (zero).

  • NSArray 和NSMutableArray—数组是对象的有序集合。你可以通过指定对象在数组中的位置(即它的索引)来访问对象。数组中的第一个元素的索引为0.

  • NSDictionary and NSMutableDictionary—A dictionary stores its entries as key-value pairs; the key is a unique identifier, usually a string, and the value is the object you want to store. You access this object by specifying the key.

  • NSDictionaryNSMutableDictionary——字典把它们的条目以键—值对的形式存储起来;这个键是一个唯一的标识符,通常是一个字符串,而值就是你要存储的对象。指定某个键然后你就可以访问对应的对象。

  • NSSet and NSMutableSet—A set stores an unordered collection of objects with each object occurring only once. You generally access objects in the set by applying tests or filters to objects in the set.

  •  

     NSSetNSMutableSet——无序集合储存了若干对象的一个无序集合,其中的每一个对象仅出现一次。通常可以向无序集合中的对象发送应用程序检测和筛选器来访问无序集合中的对象。

Because of their storage, access, and performance characteristics, one type of collection can be better suited to a particular task than another one.

因为它们的存取,访问和执行特点,某一类集合会比另一个更适合某个特定的任务。

Store Objects in a Certain Order in Arrays

在数组中按顺序存储对象

Arrays store objects in an ordered sequence. Thus, you use arrays when the order of objects in the collection is important. For example, many applications use arrays to give content to the rows of a table view or the items in a menu; the object at index 0 corresponds to the first row, the object at index 1 corresponds to the second row, and so on. Access times for objects in arrays are slower than they are for objects in a set.

数组以一个安排好的顺序存储对象。因此,当集合中对象的顺序很重要的时候请使用数组。比如说,许多应用程序使用数组来给表视图行或者菜单中的项目做目录;在索引0的对象相当于第一行,在索引1的对象相当于第二行,依此类推。访问数组中对象的时间要比访问无序集合中对象的时间慢。

The NSArray class gives you many initializers and class factory methods for creating and initializing arrays, but a few methods are particularly common and useful. You can create an array from a series of objects with the arrayWithObjects:count: and arrayWithObjects: methods (and their corresponding initializers). With the former method the second parameter specifies the number of objects in the first parameter; with the latter method, you terminate the comma-separated series of objects with nil.

NSArray类提供了很多用来创建和初始化数组的初始化程序和类工厂方法,但只有少数方法尤其常见和实用。你可以使用arrayWithObjects:count:arrayWithObjects: 方法(以及相应的初始化程序)来从一系列对象中创建数组。前面一个方法中,第二个参数指定了第一个参数中对象的号码;后面一个方法中,使用nil作为逗号分隔开的一系列对象的末尾。

// Compose a static array of string objects
NSString *objs[3] = {@"One", @"Two", @"Three"};
// Create an array object with the static array
NSArray *arrayOne = [NSArray arrayWithObjects:&(*objs) count:3];
// Create an array with a nil-terminated list of objects
NSArray *arrayTwo = [[NSArray alloc] initWithObjects:@"One", @"Two", @"Three", nil];

When creating mutable arrays, you can use the arrayWithCapacity: (or initWithCapacity:) method to create the array. The capacity parameter gives a hint to the class about the expected size of the array, thus making the array more efficient at runtime. Moreover, the array can exceed the specified capacity.

当你需要创建可变数组的时候,你可以使用 arrayWithCapacity: (或者initWithCapacity:)  方法。容量参数会给类一个数组预期大小的一个暗示,这样使得数组在运行的时候更加有效率。此外数组也可以超过指定的容量。

Generally, you call the objectAtIndex: method to access an object in an array by specifying its index position (zero-based) in the array:

一般的,可以调用 objectAtIndex: 方法通过指定对象在数组中的索引位置(从零开始的)来访问对象:

NSString *theString = [arrayTwo objectAtIndex:1]; // returns second object in array

NSArray gives you other methods to access either the objects in an array or their indexes. For example, there is lastObjectfirstObjectCommonWithArray:, and indexOfObjectPassingTest:.

NSArray提供了其它的用来访问数组中的对象或者对象索引的方法。比如说lastObjectfirstObjectCommonWithArray: indexOfObjectPassingTest:方法。

Another common task with arrays is to do something with each of the objects in the array—this is a procedure known as enumeration. You often enumerate arrays to determine whether an object or objects match a certain value or condition and, if one does, complete an action with it. You can take one of three approaches for enumerating arrays: fast enumeration, enumeration with a block, or using an NSEnumerator object. Fast enumeration, as its name implies, is typically faster than using other techniques to access the objects in an array. Fast enumeration is a language feature that requires a specific syntax:

数组的另一个常见工作和数组中的每个对象一起做点什么——一个被称为枚举的程序。通常会枚举数组来确定是否有一个或几个对象与某一个值或条件相匹配,如果有,就用它完成一些功能。你可以使用下面三种方法中的一种来枚举数组:快速枚举,模块枚举或者使用一个NSEnumerator对象。 快速枚举,顾名思义,通常能比其它方法更快地访问数组中的对象。快速枚举是一个需要特定语法的语言功能:

for (type variable in array)  }

For example:

例如:

NSArray *myArray = // get array
for (NSString *cityName in myArray) {
    if ([cityName isEqualToString:@"Cupertino"]) {
        NSLog(@"We're near the mothership!");
        break;
    }
}

Several NSArray methods enumerate arrays with blocks, the simplest of them being enumerateObjectsUsingBlock:. The block has three parameters: the current object, its index, and a by-reference Boolean value, which if set to YES terminates the enumeration. The code in the block performs exactly the same work as the code between the braces in a fast-enumeration statement.

有几个NSArray方法使用模块来枚举数组,最简单的例子就是enumerateObjectsUsingBlock:。这个模块含有三个参数:当前对象,对象索引以及引用的布尔值,这个布尔值一旦被设置为YES就结束枚举。模块中的代码与快速枚举声明中大括号之间的代码执行的是完全相同的工作。

NSArray *myArray = // get array
[myArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
    if ([(NSString *)obj isEqualToString:@"Cupertino"]) {
        NSLog(@"We're near the mothership!");
        *stop = YES;
    }
}];

NSArray has other methods that sort arrays, search arrays, and invoke a method on each object in an array.

NSArray还有一些其它的类,诸如给数组排序,搜索数据以及对数组中的每一个对象调用方法。

You can add an object to a mutable array by calling the addObject: method; the object is placed at the end of the array. You can also use insertObject:atIndex: to put an object at a particular location in an array. You can remove an object from a mutable array by calling the removeObject: method or the removeObjectAtIndex: method.

你可以通过调用addObject:方法来添加一个对象到可变数组中;这个对象会被放在数组末尾。你也可以使用insertObject:atIndex:来把一个对象放在数组中的特定位置。你可以通过调用removeObject:或者 removeObjectAtIndex:方法来从可变数组中移出一个对象。

Store Key-Value Pairs in Dictionaries

在字典中储存“键-值”对

You use a dictionary to store objects as key-value pairs—that is, an identifier (a key) is paired with an object (a value). Dictionaries are unordered collections because the key-value pairs can be in any order. Although a key can be virtually anything, it is typically a string that describes the value—for example, NSFileModificationDate orUIApplicationStatusBarFrameUserInfoKey (which are string constants). When there are public keys, dictionaries are a great way to pass information of any kind between objects.

你可以使用字典来储存“键-值”对对象——一个标识符(键)与一个对象(值)组成一对。字典是无序集合,因为“键-值”对可以以任何顺序排列。尽管键几乎可以是任何东西,但通常是描述那个值的字符串——比如说NSFileModificationDate或者UIApplicationStatusBarFrameUserInfoKey (字符串常量)。当有公共秘钥时字典是一个在对象之间传递各种信息的一个好方式。

Through its initializers and class factory methods, the NSDictionary class gives you many ways to create dictionaries, but two class methods are particularly common: dictionaryWithObjects:forKeys: and dictionaryWithObjectsAndKeys: (or their corresponding initializers). With the former method, you pass in an array of objects and an array of keys; the keys are positionally matched with their values. With the second method, you specify the first object value and then its key, the second object value and then its key, and so on; you signal the end of this series of objects with nil.

通过初始化程序和类工厂方法,NSDictionary类提供了很多创建字典的方法,但有两个类方法尤其普遍:dictionaryWithObjects:forKeys:和 dictionaryWithObjectsAndKeys: (或者对应的初始化程序)。在第一个方法中你传递了一个对象数组和一个钥匙数组;钥匙在位置上也它们的值相对应。在第二个方法中你指定第一个对象值和它的钥匙,第二个对象值和它的钥匙,依此类推;最后在这组对象的结尾以nil做标志。

// First create an array of keys and a complementary array of values
NSArray *keyArray = [NSArray arrayWithObjects:@"IssueDate", @"IssueName", @"IssueIcon", nil];
NSArray *valueArray = [NSArray arrayWithObjects:[NSDate date], @"Numerology Today",
    self.currentIssueIcon, nil];
// Create a dictionary, passing in the key array and value array
NSDictionary *dictionaryOne = [NSDictionary dictionaryWithObjects:valueArray forKeys:keyArray];
// Create a dictionary by alternating value and key and terminating with nil
NSDictionary *dictionaryTwo = [[NSDictionary alloc] initWithObjectsAndKeys:[NSDate date],
    @"IssueDate", @"Numerology Today", @"IssueName", self.currentIssueIcon, @"IssueIcon", nil];

You access an object value in a dictionary by calling the objectForKey: method, specifying a key as a parameter.

通过调用objectForKey:方法可以访问字典中的一个对象值,你需要指定一个钥匙作为参数。

NSDate *date = [dictionaryTwo objectForKey:@"IssueDate"];

You can insert and delete items in mutable dictionaries by calling the setObject:forKey: and removeObjectForKey:methods. setObject:forKey: replaces any existing value for the given key. These methods are fast.

通过调用setObject:forKey:removeObjectForKey:方法可以在可变字典中添加和删除项目。 setObject:forKey:可以移除指定秘钥所对应的任何存在的值。这些方法都是很快速的。

Store Unordered Objects in Sets

在无序数组中存储无序对象

Sets are collection objects similar to arrays except the items they contain are unordered instead of ordered. Rather than access objects in the set by index location or through a key, you access them randomly (anyObject), by enumerating the collection, or by applying a filter or test to the set.

无序集合也是一种集合,它的对象和数组的和相似只是它们的项目是无序的而不是有序的。你可以通过枚举集合,向无序集合中的对象发送应用程序检测和筛选器的方式随意地访问对象(任意对象),而不是通过索引位置或者秘钥来访问无序集合中的对象。

Although set objects are not as common in Objective-C programming as dictionaries and arrays, they are an important collection type in certain technologies. In Core Data (a data-management technology), when you declare a property for a to-many relationship, the property type should be NSSet or NSOrderedSet. Sets are also important in native touch-event handling in the UIKit framework, for example:

尽管无序集合对象在Objective-C编程中并不像字典和数组那么常见,它们在某些技术中是一个重要的集合类型。在Core Data(一种数据管理技术)中,当你声明了一个一对多关系地属性地时候,这个属性的类型应该是NSSet或者NSOrderedSet类型。在UIKit framework的本机触摸事件处理中无序集合也是很重要的,例如:

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {

 

    UITouch *theTouch = [touches anyObject];

 

    // handle the touch.....

 

}

Ordered sets are an exception to the basic definition of a set. In an ordered set, the order of the items in the set is important. Testing for membership in an ordered set is faster than it is in an array.

排好序的无序集合是无序集合基本定义的一个例外。在排好序的无序集合中,项目的顺序是关键。对所有成员的测试也比在数组中的快。

你可能感兴趣的:(Acquire Basic Programming Skills)