NSArray数组代表元素有序、可重复的一个集合,集合中每个元素都有其对应的顺序索引,可以通过索引来访问指定位置的集合元素。
NSArray的功能与用法
NSArray分别提供了类方法和实例方法来创建NSArray,两种创建方式需要传入的参数基本相似,只是类方法以array开头,而实例方法则以init开头。
下面程序示范了NSArray集合的常规用法:
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSArray* array = [NSArray arrayWithObjects:
@"疯狂iOS讲义",
@"疯狂Android讲义",
@"疯狂Ajax讲义",
@"疯狂XML讲义",
@"疯狂Swift讲义",
nil];
NSLog(@"第一个元素为:%@" , [array objectAtIndex:0]);
NSLog(@"索引为1的元素为:%@" , [array objectAtIndex:1]);
NSLog(@"最后一个元素为:%@" , [array lastObject]);
//获取从索引为2的元素开始,以及后面3个元素组成的新集合
NSArray* arr1 = [array objectsAtIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(2, 3)]];
NSLog(@"%@" , arr1);
//获取元素在集合指定位置范围中的位置
NSLog(@"在2~5范围疯狂Android讲义的位置为:%ld" , [array indexOfObject:@"疯狂Android讲义"]);
//获取元素在集合中的位置
NSLog(@"疯狂Android讲义的位置为%ld" , [array indexOfObject:@"疯狂Android讲义" inRange:NSMakeRange(2, 3)]);
//向数组的最后追加一个元素
//原NSArray本身并没有改变,只是将新返回的NSArray赋给array
array = [array arrayByAddingObject:@"孙悟空"];
//向array数组的最后追加另一个数组的所有元素
//原NSArray本身并没有改变,只是将新返回的NSArray赋给array
array = [array arrayByAddingObjectsFromArray:[NSArray arrayWithObjects:@"宝玉", @"黛玉", nil]];
for (int i = 0; i < array.count; i++) {
NSLog(@"%@" , [array objectAtIndex:i]);
//也可以写为
//NSLog(@"%@" , array[i]);
}
//获取array数组中索引为5-8的所有元素
NSArray* arr2 = [array subarrayWithRange:NSMakeRange(5, 3)];
// NSLog(@"%@" , [array objectAtIndex:0]);
//将NSArray集合写入文件
[arr2 writeToFile:@"/Users/haoqianbiao/Desktop/test1/practice/数组/未命名.txt" atomically:YES];
}
return 0;
}
程序遍历NSArray集合时,既可以通过调用NSArray的objectAtIndex:index方法来访问指定索引处的元素,也可以直接使用类似普通数组的下标表示法来访问元素。
[array objectAtIndex:i];
array[i];
但是后一种方法只能在iOS 5.0 以上的系统中使用。当程序调用array[i]语法来访问元素时,实际上就是调用NSArray的objectAtIndexedSubscript:方法进行访问。
运行以上结果,将看到如下运行结果:
不管上面的哪一种方法,都不会对原有NSArray产生任何修改(因为NSArray集合本身是不能修改的),程序只是返回一个新的NSArray对象。
从上面程序输出的结果可以看出,当程序直接输出NSArray集合,虽然会输出集合元素,但对于中文字符,则转为形如“\U75af”格式的Unicode表示形式。
NSArray判断指定元素位于NSArray集合中的索引的标准只有一条:只有某个集合元素与被查找元素通过isEqual: 方法比较返回YES时,才可以认为该NSArray集合包含该元素,并不需要两个元素是同一个元素。
下面代码证实NSArray的比较机制:
//FKUser.h
#import <Foundation/Foundation.h>
@interface FKUser : NSObject
@property (nonatomic , copy) NSString* name;
@property (nonatomic , copy) NSString* pass;
- (id) initWithName: (NSString*) aName pass:(NSString*) pass;
- (void) say:(NSString*) content;
@end
//FKUser.m
#import "FKUser.h"
@implementation FKUser
- (id) initWithName:(NSString *) aName pass:(NSString *) apass {
if (self = [super init]) {
self.name = aName;
self.pass = apass;
}
return self;
}
- (BOOL) isEqual:(id)other
{
if (self == other) {
return YES;
}
if ([other class] == FKUser.class) {
FKUser* target = (FKUser*)other;
return [self.name isEqualToString:target.name];
}
return NO;
}
- (id) description {
return self.name;
}
- (void) say:(NSString *)content {
NSLog(@"%@说:%@" , self.name , content);
}
@end
//main.m
#import <Foundation/Foundation.h>
#import "FKUser.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSArray* array = @[
[[FKUser alloc] initWithName:@"sun" pass:@"123"],
[[FKUser alloc] initWithName:@"bai" pass:@"345"],
[[FKUser alloc] initWithName:@"zhu" pass:@"654"],
[[FKUser alloc] initWithName:@"tang" pass:@"178"],
[[FKUser alloc] initWithName:@"niu" pass:@"155"]
];
//查找指定新的FKUser对象在集合中的索引
FKUser* newUser = [[FKUser alloc] initWithName:@"zhu" pass:@"654"];
NSUInteger pos = [array indexOfObject:newUser];
NSLog(@"newUser的位置为:%ld" , pos);
}
return 0;
}
对集合元素整体调用方法
NSArray允许对集合中所有的元素或部分元素整体调用方法。
示例:
#import <Foundation/Foundation.h>
#import "FKUser.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSArray* array = @[
[[FKUser alloc] initWithName:@"sun" pass:@"123"],
[[FKUser alloc] initWithName:@"bai" pass:@"345"],
[[FKUser alloc] initWithName:@"zhu" pass:@"654"],
[[FKUser alloc] initWithName:@"tang" pass:@"178"],
[[FKUser alloc] initWithName:@"niu" pass:@"155"]
];
//对集合元素整体调用方法
[array makeObjectsPerformSelector:@selector(say:) withObject:@"下午好,NSArray真强大!"];
NSString* content = @"疯狂iOS讲义";
//迭代集合内指定范围内的元素,并使用该元素来执行代码
[array enumerateObjectsAtIndexes:[NSIndexSet indexSetWithIndexesInRange: NSMakeRange(2, 2)] options:NSEnumerationReverse usingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
NSLog(@"正在处理第%ld个元素:%@" , idx , obj);
[obj say:content];
}];
}
return 0;
}
效果:
对NSArray进行排序
NSArray提供了大量的方法对集合元素进行排序,这些排序都以sorted开头。
示例:
#import <Foundation/Foundation.h>
NSComparisonResult intSort (id num1, id num2, void *context) {
int v1 = [num1 intValue];
int v2 = [num2 intValue];
if (v1 < v2) {
return NSOrderedAscending;
} else if (v1 > v2) {
return NSOrderedDescending;
} else {
return NSOrderedSame;
}
}
int main(int argc, const char * argv[]) {
@autoreleasepool {
//初始化一个元素为NSString的NSArray对象
NSArray* array1 = @[@"Objective-C" , @"C" , @"C++" , @"Ruby" , @"Perl" , @"Swift"];
//使用集合元素的compare:方法进行排序
array1 = [array1 sortedArrayUsingSelector:@selector(compare:)];
NSLog(@"%@" , array1);
//初始化一个元素为NSNumber的NSArray对象
NSArray* array2 = @[[NSNumber numberWithInt:20] ,
[NSNumber numberWithInt:12] ,
[NSNumber numberWithInt:-8] ,
[NSNumber numberWithInt:50] ,
[NSNumber numberWithInt:19] ];
array2 = [array2 sortedArrayUsingFunction:intSort context:nil];
NSLog(@"%@" , array2);
//使用代码块对集合元素进行排序
NSArray* array3 = [array2 sortedArrayUsingComparator: ^(id obj1 , id obj2)
{
//该代码块就是根据元素的intValuei进行比较
if ([obj1 intValue] > [obj2 intValue]) {
return NSOrderedDescending;
}
if ([obj1 intValue] < [obj2 intValue])
{
return NSOrderedAscending;
}
return NSOrderedSame;
}];
NSLog(@"%@" , array3);
}
return 0;
}
效果:
使用枚举器遍历NSArray元素
对于NSArray对象,除了可根据集合元素的索引来遍历集合元素之外,还可以调用NSArray对象的以下两个方法来返回枚举器。
1.objectEnumerator:返回NSArray集合的枚举器。
reverseObjectEnumerator:返回NSArray集合的逆序枚举器。
上面两个方法都返回一个NSEnumerator枚举器,该枚举器只包含以下两个方法。
1.allObjects:获取被枚举集合中的所有元素
2.nextObject:获取被枚举集合中的下一个元素。
一般来说,借助nextObject方法即可对集合元素进行枚举:程序可以采用循环不断获得nextObject方法的返回值,直到该方法的返回值为nil结束循环。
示例:
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
@autoreleasepool {
//读写前面写入磁盘的文件,用文件内容来初始化NSArray集合
NSArray* array = [NSArray arrayWithContentsOfFile:@"/Users/haoqianbiao/Desktop/test1/practice/数组/未命名.txt"];
//获取NSArray的顺序枚举器
NSEnumerator* en = [array objectEnumerator];
id object;
while (object = [en nextObject]) {
NSLog(@"%@" , object);
}
NSLog(@"------下面顺序遍历------");
//获取NSArray的逆序枚举器
en = [array reverseObjectEnumerator];
while (object = [en nextObject]) {
NSLog(@"%@" , object);
}
}
return 0;
}
效果:
快速枚举(for-in)
语法格式:
for(type variableName in collection)
{
//variableName自动迭代访问每个元素...
}
在上面的语法格式中,type是集合元素的类型,variableName是一个形参名,快速枚举自动将集合元素依次赋给该变量。
示例:
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
@autoreleasepool {
//读取前面写入磁盘的文件,用文件内容来初始化NSArray集合
NSArray* array = [NSArray arrayWithContentsOfFile:@"/Users/haoqianbiao/Desktop/test1/practice/数组/未命名.txt"];
for (id object in array) {
NSLog(@"%@" , object);
}
}
return 0;
}
可变数组
NSArray代表集合元素不可变的集合,一旦NSArray创建成功。程序就不能向集合中添加新的元素,不能删除集合中已有的元素,也不能替换集合中的元素。
注:NSArray只是保存对象的指针,因此NSArray只保证这些变量指针中的地址不能改变,但指针变量所指向的对象是可以改变的。
NSArray有一个子类:NSMutableArray,因此它可以作为NSArray使用,它代表的是一个集合元素可变的集合。
示例:
#import <Foundation/Foundation.h>
NSString* NSCollectionToString(NSArray* array) {
NSMutableString* result = [NSMutableString stringWithString:@"["];
for (id obj in array) {
[result appendString:[obj description]];
[result appendString:@", "];
}
NSUInteger len = [result length];
//去掉字符串最后两个字符
[result deleteCharactersInRange:NSMakeRange(len - 2, 2)];
[result appendString:@"]"];
return result;
}
int main(int argc, const char * argv[]) {
@autoreleasepool {
//读取前面写入磁盘的文件,用文件内容来初始化NSMutableArray
NSMutableArray* array = [NSMutableArray arrayWithContentsOfFile:@"/Users/haoqianbiao/Desktop/test1/practice/数组/未命名.txt"];
[array addObject:@"疯狂iOS讲义"];//向集合最后添加一个元素
NSLog(@"最后一个追加元素后%@" , NSCollectionToString(array));
//使用NSArray向集合尾部添加多个元素
[array addObjectsFromArray:[NSArray arrayWithObjects:@"张飞" , @"关羽" , nil]];
NSLog(@"最后追加两个元素后:%@" , NSCollectionToString(array));
//向集合的指定位置插入一个元素
[array insertObject:@"疯狂Ajax讲义" atIndex:2];
NSLog(@"在索引为2处插入一个元素后:%@" , NSCollectionToString(array));
//使用NSArray向集合指定位置插入多个元素
[array insertObjects:[NSArray arrayWithObjects:@"武松" , @"林冲" , nil] atIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(3, 2)]];
NSLog(@"插入多个元素后:%@" , NSCollectionToString(array));
[array removeLastObject];
NSLog(@"删除最后一个元素后%@" , NSCollectionToString(array));
[array removeObjectAtIndex:5];
NSLog(@"删除索引为5处的元素后:%@" , NSCollectionToString(array));
[array removeObjectsInRange:NSMakeRange(2, 3)];
NSLog(@"删除索引为2~4处的元素后:%@" , NSCollectionToString(array));
//替换索引为2处的元素
[array replaceObjectAtIndex:2 withObject:@"疯狂iOS讲义"];
NSLog(@"替换索引2处的元素后:%@" , NSCollectionToString(array));
}
return 0;
}
效果:
NSArray的KVC与KVO
NSArray是一个容纳多个对象的集合,NSArray允许直接对集合中的所有元素进行整体的KVC编码。
示例:
#import <Foundation/Foundation.h>
#import "FKUser.h"
NSString* NSCollectionToString(NSArray* array) {
NSMutableString* result = [NSMutableString stringWithString:@"["];
for (id obj in array) {
[result appendString:[obj description]];
[result appendString:@", "];
}
NSUInteger len = [result length];
//去掉字符串最后两个字符
[result deleteCharactersInRange:NSMakeRange(len - 2, 2)];
[result appendString:@"]"];
return result;
}
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSArray* array = @[
[[FKUser alloc] initWithName:@"Hello1"],
[[FKUser alloc] initWithName:@"Hello2"],
[[FKUser alloc] initWithName:@"Hello3"]];
id newArr = [array valueForKey:@"name"]; // 1
NSLog(@"%@" , NSCollectionToString(newArr));
//对集合中的所有元素整体进行KVC编程
//将所有集合元素的name属性改为新名字
[array setValue:@"新名字" forKey:@"name"]; // 2
NSLog(@"%@" , NSCollectionToString(array));
}
return 0;
}
上面的程序中“1、2”行代码对集合元素整体进行了KVC编程,其中第“1”行代码获取所有集合元素的name属性组成的数组;第“2”行代码将所有的集合元素的name属性都设为新值。
效果: