//---------接口声明-----------
@interface XYZPerson : NSObject
@property int age;
-(void)gettingOlder;
@end
//----------接口实现-----------
@implementation XYZPerson
-(void)gettingOlder{
_age +=1;
//same as
++_age;
//还可以像下面这样
self.age = self.age + 1;
self.age++;
}
@end
It’s best practice to use these platform-specific types if you might be passing values across API boundaries (both internal and exported APIs), such as arguments or return values in method or function calls between your application code and a framework.
若需要向某个框架外的API传递参数,比如你的应用代码和框架之间的参数传递,最好使用这些与平台相关的数据类型。
- 在64位的OSX系统内,int在OC中是32位的。而long int是64位的。
- float和double分别是32位和64位的。
Some Cocoa and Cocoa Touch API use C structures to hold their values.
- 有些框架内的API使用C的struct来保存值。
NSString *mainString = @"This is a long string";
NSRange substringRange = [mainString rangeOfString:@"long"];
//Strings Are Represented by Instances of the NSString Class
NSString *firstString = [[NSString alloc] initWithCString:"Hello World!"
encoding:NSUTF8StringEncoding];
NSString *secondString = [NSString stringWithCString:"Hello World!"
encoding:NSUTF8StringEncoding];
NSString *thirdString = @"Hello World!";
If you need to represent a different string, you must create a new string object
- 在使用NSString类的时候,如果需要表示另外一个字符串,就必须建立一个新的对象。
NSString *name = @"John";
name = [name stringByAppendingString:@"ny"]; // returns a new string object
The NSMutableString class is the mutable subclass of NSString
NSMutableString *name = [NSMutableString stringWithString:@"John"];
[name appendString:@"ny"]; // same object, but now represents "Johnny"
int magicNumber = ...
NSString *magicString = [NSString stringWithFormat:@"The magic number is %i", magicNumber];
The NSNumber class is used to represent any of the basic C scalar types, including char, double, float, int, long, short, and the unsigned variants of each, as well as the Objective-C Boolean type, BOOL.
- NSNumber可以用来表示任何的C数值类型,int、long、short、double、float、char,,以及它们的无符号形式。另外还有OC种的布尔类型BOOL。
you have a variety of options to create NSNumber instances, including allocation and initialization or the class factory methods:
- 有多种建立NSNumber的方法,比如使用alloc和init,以及类的构造方法:
//使用alloc分配内存和init初始化方法
NSNumber *magicNumber = [[NSNumber alloc] initWithInt:42];
NSNumber *unsignedNumber = [[NSNumber alloc] initWithUnsignedInt:42u];
NSNumber *longNumber = [[NSNumber alloc] initWithLong:42l];
NSNumber *boolNumber = [[NSNumber alloc] initWithBOOL:YES];
//直接使用构造方法
NSNumber *simpleFloat = [NSNumber numberWithFloat:3.14f];
NSNumber *betterDouble = [NSNumber numberWithDouble:3.1415926535];
NSNumber *someChar = [NSNumber numberWithChar:'T'];
NSNumber *magicNumber = @42;
NSNumber *unsignedNumber = @42u;
NSNumber *longNumber = @42l;
NSNumber *boolNumber = @YES;
NSNumber *simpleFloat = @3.14f;
NSNumber *betterDouble = @3.1415926535;
NSNumber *someChar = @'T';
int scalarMagic = [magicNumber intValue];
unsigned int scalarUnsigned = [unsignedNumber unsignedIntValue];
long scalarLong = [longNumber longValue];
BOOL scalarBool = [boolNumber boolValue];
float scalarSimpleFloat = [simpleFloat floatValue];
double scalarBetterDouble = [betterDouble doubleValue];
char scalarChar = [someChar charValue];
The NSNumber class also offers methods to work with the additional Objective-C primitive types.
NSInteger anInteger = 64;
NSUInteger anUnsignedInteger = 100;
NSNumber *firstInteger = [[NSNumber alloc] initWithInteger:anInteger];
NSNumber *secondInteger = [NSNumber numberWithUnsignedInteger:anUnsignedInteger];
NSInteger integerCheck = [firstInteger integerValue];
NSUInteger unsignedCheck = [secondInteger unsignedIntegerValue];
All NSNumber instances are immutable, and there is no mutable subclass; if you need a different number, simply use another NSNumber instance.
**Note: **NSNumber is actually a class cluster. This means that when you create an instance at runtime, you’ll get a suitable concrete subclass to hold the provided value. Just treat the created object as an instance of NSNumber.
NSNumber class is itself a subclass of the basic NSValue class.which provides an object wrapper around a single value or data item
NSValue can also be used to represent pointers and structures.
The NSValue class offers various factory methods to create a value with a given standard structure, which makes it easy to create an instance to represent.
-在NSValue类里面提供了许多的构造方法表示一个给定的结构,以便于建立对象。代码如下所示:(这样有毛用?)
NSString *mainString = @"This is a long string";
NSRange substringRange = [mainString rangeOfString:@"long"];
NSValue *rangeValue = [NSValue valueWithRange:substringRange];
It’s also possible to create NSValue objects to represent custom structures. If you have a particular need to use a C structure (rather than an Objective-C object) to store information
typedef struct {
int i;
float f;
} MyIntegerFloatStruct;
you can create an NSValue instance by providing a pointer to the structure as well as an encoded Objective-C type. The @encode() compiler directive is used to create the correct Objective-C type
- 上面的结构可以存储在NSValue类对象里,只需要提供一个该结构的指针即可,它就相当于一个OC类型。使用@encode()编译指令来建立一个合适的OC类型。
//定义一个MyIntegerFloatStruct类变量aStruct
struct MyIntegerFloatStruct aStruct;
//对结构内的变量赋值
aStruct.i = 42;
aStruct.f = 3.14;
//两个参数,第一个是aStruct变量的地址,第二个是使用@encode编译器指令建立的ObjType
NSValue *structValue = [NSValue value:&aStruct
withObjCType:@encode(MyIntegerFloatStruct)];
Although it’s possible to use a C array to hold a collection of scalar values, or even object pointers, most collections in Objective-C code are instances of one of the Cocoa and Cocoa Touch collection classes, like NSArray, NSSet and NSDictionary.
虽然可以使用C数组来存储数值集合、对象指针集合,但OC中的绝大多数集合都是框架类NSArray、NSSet、NSDictionary的实例。它们里存放的必须是OC类的对象。
If you need to add a scalar value, you must first create a suitable NSNumber or NSValue instance to represent it.
如果需要向它们里添加一个数值,必须首先建立一个合适的NSNumber或NSValue对象来表示这个数值。
collection classes use strong references to keep track of their contents
集合类使用强引用来追踪它里面的对象。
The basic NSArray, NSSet and NSDictionary classes are immutable, which means their contents are set at creation. Each also has a mutable subclass to allow you to add or remove objects at will.
The only requirement is that each item is an Objective-C object— there’s no requirement for each object to be an instance of the same class.
- 唯一的条件就是待存放的元素都是OC中的对象,但是不需要让每一个对象都是相同类型的。
you can create an array through allocation and initialization, class factory methods, or literal syntax.
- 可用使用alloc和init、类构造方法、字面量来建立数组。There are a variety of different initialization and factory methods available, depending on the number of objects.
+ (id)arrayWithObject:(id)anObject;
+ (id)arrayWithObjects:(id)firstObject, ...;
- (id)initWithObjects:(id)firstObject, ...;
The arrayWithObjects: and initWithObjects: methods both take a nil-terminated, variable number of arguments, which means that you must include nil as the last value
arrayWithObjects和initWithObjects构造方法都是以nil参数结尾,并且未限制参数的数量。
NSArray *someArray =
[NSArray arrayWithObjects:someObject, someString, someNumber, someValue, nil];
id firstObject = @"someString";
id secondObject = nil;
id thirdObject = @"anotherString";
NSArray *someArray =
[NSArray arrayWithObjects:firstObject, secondObject, thirdObject, nil];
以上面的方法建立的数组,secondObject的值是nil,那建立起来的数组就只包含一个firstObject。
nil would be interpreted as the end of the list of items.
记住nil是作为对象列表的结束标志来使用的。
NSArray *someArray = @[firstObject, secondObject, thirdObject];
You should not terminate the list of objects with nil when using this literal syntax, and in fact nil is an invalid value. You’ll get an exception at runtime if you try to execute the following code.
id firstObject = @"someString";
id secondObject = nil;
NSArray *someArray = @[firstObject, secondObject];
// exception: "attempt to insert nil object"
Once you’ve created an array, you can query it for information like the number of objects, or whether it contains a given item:
- 建立数组之后,就可以查询它里面的信息了。比如对象数目,或者是里面是否包含特定对象:
//对象方法count用于获得对象数目
NSUInteger numberOfItems = [someArray count];
//containsObject方法用于查询特定对象
if ([someArray containsObject:someString]) {
...
}
You can also query the array for an item at a given index. You’ll get an out-of-bounds exception at runtime if you attempt to request an invalid index.
也可以通过下标查询。如果尝试越界的下标查询,则会出现运行时错误。可以像下面这样保证数组中有对象才进行查询:
//数组内存放对象数目大于0才进行查询
if ([someArray count] > 0) {
//使用objectAtIndex方法获得指定下标对象:
NSLog(@"First item is: %@", [someArray objectAtIndex:0]);
}
使用下面的方式可以对原数组排序并生产新数组:
//原unsortedStrings里面的对象未排序
NSArray *unsortedStrings = @[@"gammaString", @"alphaString", @"betaString"];
//使用sortedArrayUsingSelector方法来获得一个排序后的新对象,并赋值给sortedStrings,“选择器selector使用compare方法”
NSArray *sortedStrings =
[unsortedStrings sortedArrayUsingSelector:@selector(compare:)];
虽然NSArray是不可变的,但不会影响到它里面存放的对象,看如下代码:
NSMutableString *mutableString = [NSMutableString stringWithString:@"Hello"];
NSArray *immutableArray = @[mutableString];
//元素数目>0
if ([immutableArray count] > 0) {
//将下标0的元素赋值给string
id string = immutableArray[0];
//当string是可变字符串类的话
if ([string isKindOfClass:[NSMutableString class]]) {
//修改里面的值为World!
[string appendString:@" World!"];
}
}
If you need to be able to add or remove objects from an array after initial creation, you’ll need to use NSMutableArray.
NSMutableArray *mutableArray = [NSMutableArray array];
[mutableArray addObject:@"gamma"];
[mutableArray addObject:@"alpha"];
[mutableArray addObject:@"beta"];
[mutableArray replaceObjectAtIndex:0 withObject:@"epsilon"];
It’s also possible to sort a mutable array in place, without creating a secondary array.
[mutableArray sortUsingSelector:@selector(caseInsensitiveCompare:)];
An NSSet is similar to an array, but maintains an unordered group of distinct objects.
NSSet和NSArray类似,只是里面的对象彼此之间不存在顺序关系。
Because sets don’t maintain order, they offer a performance improvement over arrays when it comes to testing for membership.
sets并没有在内部维护对象间顺序,在归属测试的时候可以比数组有更好的性能。
The basic NSSet class is again immutable, so its contents must be specified at creation, using either allocation and initialization or a class factory method.
NSSet *simpleSet =
[NSSet setWithObjects:@"Hello, World!", @42, aValue, anObject, nil];
As with NSArray, the initWithObjects: and setWithObjects: methods both take a nil-terminated.
Rather than simply maintaining an ordered or unordered collection of objects, an NSDictionary stores objects against given keys, which can then be used for retrieval.
It’s best practice to use string objects as dictionary keys.
Note: It’s possible to use other objects as keys, but it’s important to note that each key is copied for use by a dictionary and so must support NSCopying.
If you wish to be able to use Key-Value Coding, however, as described in Key-Value Coding Programming Guide, you must use string keys for dictionary objects.
- 可以用其他类型对象作为关键字,但需要注意的是,字典中用作关键字都是对象的拷贝,所以用作关键字的对象必须支持NSCopying。如果你需要使用Key-Value Coding,你就必须使用string类的对象作为关键字。(Key-Value Coding详见Key-Value Coding Programming Guide。)
//同样以nil结尾,是按 对象,关键字 的顺序进行建立的
NSDictionary *dictionary = [NSDictionary dictionaryWithObjectsAndKeys:
someObject, @"anObject",
@"Hello, World!", @"helloString",
@42, @"magicNumber",
someValue, @"aValue",
nil];
Objective-C also offers a literal syntax for dictionary creation
NSDictionary *dictionary = @{
@"anObject" : someObject,
@"helloString" : @"Hello, World!",
@"magicNumber" : @42,
@"aValue" : someValue
};
Note that for dictionary literals, the key is specified before its object and is not nil-terminated.
//字典对象的objectForKey方法,使用关键字作为参数,返回一个对象,如果没有找到则返回nil。
NSNumber *storedNumber = [dictionary objectForKey:@"magicNumber"];
//字典对象用关键字作为下标来进行索引,和数组[]类似。
NSNumber *storedNumber = dictionary[@"magicNumber"];
If you need to add or remove objects from a dictionary after creation, you need to use the NSMutableDictionary subclass.
//dictionary的setObject方法,第一个参数是对象,第二个参数是关键字
[dictionary setObject:@"another string" forKey:@"secondString"];
//remove方法,只需要指定关键字
[dictionary removeObjectForKey:@"anObject"];
It’s not possible to add nil to the collection classes described in this section because nil in Objective-C means “no object.” If you need to represent “no object” in a collection, you can use the NSNull class.
//定义了一个末尾元素是null值对象的数组
NSArray *array = @[ @"string", @42, [NSNull null] ];
NSNull is a singleton class, which means that the null method will always return the same instance. This means that you can check whether an object in an array is equal to the shared NSNull instance.
//若数组中有和NSNull的null方法返回的对象相同类型的对象,则输出:发现一个null对象。
for (id object in array) {
if (object == [NSNull null]) {
NSLog(@"Found a null object");
}
}
The NSArray and NSDictionary classes make it easy to write their contents directly to disk.
//指定文件fileURL
NSURL *fileURL = ...
//数组array
NSArray *array = @[@"first", @"second", @"third"];
//输出成功标志success为YES,表示array的writeToURL方法成功
BOOL success = [array writeToURL:fileURL atomically:YES];
//若不成的功,则。。。
if (!success) {
// an error occured...
}
If every contained object is one of the property list types (NSArray, NSDictionary, NSString, NSData, NSDate and NSNumber), it’s possible to recreate the entire hierarchy from disk.
//指定文件
NSURL *fileURL = ...
//NSArray类方法arrayWithContentOfURL
NSArray *array = [NSArray arrayWithContentsOfURL:fileURL];
if (!array) {
// an error occurred...
}
If you need to persist other types of objects than just the standard property list classes shown above, you can use an archiver object, such as NSKeyedArchiver, to create an archive of the collected objects.
The only requirement to create an archive is that each object must support the NSCoding protocol.This means that each object must know how to encode itself to an archive (by implementing the encodeWithCoder: method) and decode itself when read from an existing archive (the initWithCoder: method).
The NSArray, NSSet and NSDictionary classes, and their mutable subclasses, all support NSCoding, which means you can persist complex hierarchies of objects using an archiver. If you use Interface Builder to lay out windows and views, for example, the resulting nib file is just an archive of the object hierarchy that you’ve created visually. At runtime, the nib file is unarchived to a hierarchy of objects using the relevant classes.
Objective-C and Cocoa or Cocoa Touch offer a variety of ways to enumerate the contents of a collection. Although it’s possible to use a traditional C for loop to iterate over the contents.
虽然可以使用C中的循环来遍历一个集,但OC和框架类中提供了大量的途径去枚举集中的内容。使用C风格枚举如下所示:
//定义一个count作为iteration。
int count = [array count];
for (int index = 0; index < count; index++) {
id eachObject = [array objectAtIndex:index];
...
}
Many collection classes conform to the NSFastEnumeration protocol, including NSArray, NSSet and NSDictionary. This means that you can use fast enumeration, an Objective-C language-level feature.
//对collection中每一个Type类型的变量
for (<Type> <variable> in <collection>) {
...
}
//对数组中每一个对象进行输出(log)
for (id eachObject in array) {
NSLog(@"Object: %@", eachObject);
}
//字典中每一个NSString类的关键字
for (NSString *eachKey in dictionary) {
//因为还不知道每个关键字对于对象的类型,故用id
id object = dictionary[eachKey];
//输出格式为:“对象:关键字”
NSLog(@"Object: %@ for key: %@", object, eachKey);
}
If you are enumerating an ordered collection, the enumeration proceeds in that order. For an NSArray, this means the first pass will be for the object at index 0, the second for object at index 1, etc. If you need to keep track of the current index, simply count the iterations as they occur:
int index = 0;
for (id eachObject in array) {
NSLog(@"Object at index %i is: %@", index, eachObject);
index++;
}
You cannot mutate a collection during fast enumeration, even if the collection is mutable. If you attempt to add or remove a collected object from within the loop, you’ll generate a runtime exception.
It’s also possible to enumerate many Cocoa and Cocoa Touch collections by using an NSEnumerator object.
You can ask an NSArray, for example, for an objectEnumerator or a reverseObjectEnumerator. It’s possible to use these objects with fast enumeration.
//对array使用枚举器reverseObjectEnumerator,再进行快速枚举(按与array正向相反顺序)
for (id eachObject in [array reverseObjectEnumerator]) {
...
}
It’s also possible to iterate through the contents by calling the enumerator’s nextObject method repeatedly.
id eachObject;
while ( (eachObject = [enumerator nextObject]) ) {
NSLog(@"Current object is: %@", eachObject);
}
a while loop is used to set the eachObject variable to the next object for each pass through the loop. When there are no more objects left, the nextObject method will return nil, which evaluates as a logical value of false so the loop stops.
Note: Because it’s a common programmer error to use the C assignment operator (=) when you mean the equality operator (==), the compiler will warn you if you set a variable in a conditional branch or loop, like this:
if (someVariable = YES) {
...
}
If you really do mean to reassign a variable (the logical value of the overall assignment is the final value of the left hand side), you can indicate this by placing the assignment in parentheses, like this:
if ( (someVariable = YES) ) {
...
}
As with fast enumeration, you cannot mutate a collection while enumderating. And, as you might gather from the name, it’s faster to use fast enumeration than to use an enumerator object manually.
It’s also possible to enumerate NSArray, NSSet and NSDictionary using blocks. Blocks are covered in detail in the next chapter.