一. 数组
NSArray代表元素有序,可重复的一个集合,集合都有其对应的顺序索引。
1. NSArray的功能与用法
NSArray分别提供类方法与类实例方法创建NSArray,两种创建方法需要传入参数基本相似,类方法一array开头,而实例方法则以init开头。下面是几类常见的方法:
还可以使用简化语法来创建NSArray对象:
@[元素1,元素2,元素3,......]
参考NSArray类的文档,可以看到NSArray集合的方法大致包括如下几类。
下类代码展示了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(@":第二个元素:%@", [array objectAtIndex: 1]);
NSLog(@":第三个元素:%@", [array objectAtIndex: 2]);
//获取索引为2的元素开始,以及后面3个元素组成的新集合
NSArray* arr1 = [array objectsAtIndexes: [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(2, 3)]];
NSLog(@"%@", arr1);
//获取元素在集合中的位置
NSLog(@"疯狂Android讲义的位置:%ld",[array indexOfObject:@"疯狂Android讲义"]);
//获取元素在集合指定范围中的位置
NSLog(@"在2~5范围疯狂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]);
}
NSArray* arr2 = [array subarrayWithRange:NSMakeRange(5, 3)];
NSLog(@"%@",arr2);
}
return 0;
}
代码运行如下:
上述程序试图返回“疯狂Android讲义”字符串对象在NSArray集合中NSRange(2,3)范围,实际上该位置并没有包含该字符串对象,因此程序返回9223372036854775807,这是常量NSNotFound的值。
程序采用两种方法向NSArray集合后面追加元素:
arrayByAddingObject: 方法追加单个元素;
arrayWithObjects: 方法追加另一个数组的全部元素;
不论是用哪一种方法,对于原NSArray对象都不会产生任何修改,程序只是返回一个新的NSArray对象。
接下来展示NSArray的比较机制:
接口部分:
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface FKUser : NSObject
@property (nonatomic, copy) NSString* name;
@property (nonatomic, copy) NSString* pass;
- (id) initWithName: (NSString* ) name pass: (NSString* ) pass;
- (void) say: (NSString* ) content;
@end
NS_ASSUME_NONNULL_END
实现部分:
#import "FKUser.h"
@implementation FKUser
- (id)initWithName:(nonnull NSString *)name pass:(nonnull NSString *)pass {
if (self == [super init]) {
self.name = name;
self.pass = pass;
}
return self;
}
- (void)say:(nonnull NSString *)content {
NSLog(@"%@说:%@", self.name, content);
}
//重写isEqual:方法,重写方法的标准是如果两个FKUser的name, pass相等,即可认为他们相等。
- (BOOL) isEqual:(id) other {
if (self == other) {
return YES;
}
if ([other class] == FKUser.class) {
FKUser* target = (FKUser* ) other;
return [self.name isEqual:target.name] &&[self.pass isEqual:target.pass];
}
return NO;
}
//重写description方法,可以直接看到FKUser对象的状态
- (NSString*) description {
return [NSString stringWithFormat:@"<FKUser[name = %@, pass = %@]>", self.name, self.pass];
}
@end
主代码部分:
#import <Foundation/Foundation.h>
#import "FKUser.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
//使用简化语法创建NSArray对象
NSArray* array = @[
[[FKUser alloc] initWithName:@"sun" pass:@"123"],
[[FKUser alloc] initWithName:@"lai" pass:@"124"],
[[FKUser alloc] initWithName:@"li" pass:@"125"],
[[FKUser alloc] initWithName:@"gao" pass:@"126"],
[[FKUser alloc] initWithName:@"zhu" pass:@"127"] ];
FKUser* newUser = [[FKUser alloc] initWithName:@"li" pass:@"125"];
//查找指定新的FKUser对象在集合中的索引
NSUInteger pos = [array indexOfObject:newUser];
//打印出newUser的信息
NSLog(@"%@", [newUser description]);
NSLog(@"newUser的位置为%ld", pos);
}
return 0;
}
代码运行结果如下:
2. 对集合元素整体调用方法
NSArray允许对集合中所有元素或者部分元素整体进行调用方法,如果只是简单地调用集合元素的方法,可以通过NSArray的如下方法来实现:
如果希望对集合中的所有元素进行隐式遍历,并使用集合元素来执行某段代码,则可通过NSArray的如下方法:
下面来看代码:
#import <Foundation/Foundation.h>
#import "FKUser.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
//使用简化语法创建NSArray对象
NSArray* array = @[
[[FKUser alloc] initWithName:@"sun" pass:@"123"], [[FKUser alloc] initWithName:@"lai" pass:@"124"], [[FKUser alloc] initWithName:@"li" pass:@"125"], [[FKUser alloc] initWithName:@"gao" pass:@"126"],[[FKUser alloc] initWithName:@"zhu" pass:@"127"] ];
//对集合元素整体调用方法
[array makeObjectsPerformSelector:@selector(say:) withObject:@"下午好,iOS真强大"];
NSString* content = @"疯狂iOS讲义";
//迭代计划内指定范围内的元素,并使用该元素执行块代码
[array enumerateObjectsAtIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(2, 2)] options:NSEnumerationReverse
//代码块的第一个参数代表正在遍历的集合元素
//代码块的第二个参数代表正在便利的集合元素的索引
//代码块的第三个参数用于控制是否停止遍历,将该参数设置为NO即可停止遍历
usingBlock: ^(id obj, NSUInteger idx, BOOL *stop) {
NSLog(@"正在处理第%ld个元素: %@", idx, obj);
[obj say: content];
}];
}
return 0;
}
代码执行结果如下:
3. 对NSArray进行排序
NSArray提供了大量方法对集合元素进行排序,这些排序方法都以sorted开头,下面是几个比较常用的:
如下列代码所示对集合进行排序:
#import <Foundation/Foundation.h>
//定义比较函数,根据两个对象的inValue进行比较
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;
}
}
#import "FKUser.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
//初始化一个元素的NSString的NSArray对象
NSArray* array1 = @[@"Objective-C", @"C", @"C++", @"Ruby", @"Perl", @"Swift"];
//使用集合元素的copmare:方法进行排序
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] ];
//使用inSort函数进行排序
array2 = [array2 sortedArrayUsingFunction: intSort context: nil];
NSLog(@"%@", array2);
//使用代码块对集合元素进行排序
NSArray* array3 = [array2 sortedArrayUsingComparator:^(id obj1, id obj2) {
//该代码就是根据集合元素inValue进行比较
if ([obj1 intValue] > [obj2 intValue]) {
return NSOrderedDescending;
}
if ([obj1 intValue] < [obj2 intValue]) {
return NSOrderedAscending;
}
return NSOrderedSame;
}];
NSLog(@"%@", array3);
}
return 0;
}
代码运行结果如下:
4. 使用枚举器遍历NSArray集合元素
对于NSArray对象,除了可以更具集合的索引来遍历集合元素之外,还可以调用NSArray对象的如下两个方法来返回枚举器。
上面两个方法都返回一个NSEnumerator枚举器,。该枚举器之包含下面两个方法:
使用下面代码进行示例:
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSArray* array = [NSArray arrayWithObjects:@"孙悟空", @"赖晨煜", @"黛玉", @"宝玉", nil];
//获取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;
}
代码运行结果如下:
5. 快速枚举(for … in)
Objective-C还提供了一种快速枚举的方法来遍历集合,使用快速枚举遍历集合元素时,无需获得集合的长度,也无需根据索引来访问集合元素,即可快速枚举自动遍历集合的每一个元素。
for (type variableName in collection) {
//variableName 自动迭代访问每个元素
}
下面是代码示例:
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSArray* array = [NSArray arrayWithObjects:@"孙悟空", @"赖晨煜", @"黛玉", @"宝玉", nil];
for (id object in array) {
NSLog(@"%@", object);
}
}
return 0;
}
代码运行结果如下:
6. 可变数组(NSMutableArray)
NSArray是不可变的集合,一旦创建成功,程序不能向集合中添加新的元素,不能删除已有的元素,也不能替换集合元素。
NSMutableArray代表集合元素可变的集合,而NSMutableArray底层采用传统数组来容纳集合元素,因此创建NSMutableArray是可以通过参数指定底层数组的初始容量。
下面代码展示了如何改变NSMutableArray集合中的元素:
#import <Foundation/Foundation.h>
//定义一个函数,该函数用于把NSArray集合转换为字符串
NSString* NSCollectionToString (NSArray* array) {
NSMutableString* result = [NSMutableString stringWithString:@"["];
for (id object in array) {
[result appendString: [object 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* array = [NSMutableArray arrayWithObjects:@"孙悟空", @"赖晨煜", @"黛玉", @"宝玉", nil];
//向集合最后添加一个元素
[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(2, 3)]];
NSLog(@"插入多个元素后:%@", NSCollectionToString(array));
//删除集合最后一个元素
[array removeLastObject];
NSLog(@"删除最后一个元素后:%@", NSCollectionToString(array));
//删除集合中指定索引处的元素后
[array removeObjectAtIndex: 5];
NSLog(@"删除索引为5的元素后:%@", NSCollectionToString(array));
//删除集合中索引为2~4处的元素
[array removeObjectsInRange:NSMakeRange(2, 3)];
NSLog(@"删除索引为2~4处的元素后:%@", NSCollectionToString(array));
//替换索引为2的元素
[array replaceObjectAtIndex:2 withObject:@"疯狂Android讲义"];
NSLog(@"替换索引为2处的元素后:%@", NSCollectionToString(array));
}
return 0;
}
二.集合
NSSet是一个广泛使用的集合,但是NSSet集合中不允许包含相同的元素,如果把相同的元素放入同一个集合中,则只会保留一个元素。
NSSet不能保证元素的添加顺序,顺序有可能发生改变,与NSArray相比,NSSet最大的区别是元素没有索引,不能根据元素索引来操作元素。
1. NSSet的功能与用法
获取NSSet对象后,接下来可以调用NSSet的方法来访问元素集合:
下面代码示范了NSSet集合的基本用法:
#import <Foundation/Foundation.h>
//把集合转换为字符串
NSString* NSCollectionToString (id array) {
NSMutableString* result = [NSMutableString stringWithString:@"["];
for (id object in array) {
[result appendString: [object 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 {
//使用4个元素初始化NSSet集合
//故意传入两个相同的元素,NSSet集合只会保留一个
NSSet* set1 = [NSSet setWithObjects:@"疯狂iOS讲义", @"疯狂Android讲义", @"疯狂Ajax讲义", @"疯狂iOS讲义", nil];
//程序输出set1集合中的元素个数为3
NSLog(@"set1集合中元素个数为:%ld", [set1 count]);
NSLog(@"s1集合:%@", NSCollectionToString(set1));
NSSet* set2 = [NSSet setWithObjects:@"孙悟空", @"疯狂Android讲义", @"猪八戒", nil];
NSLog(@"s2集合:%@", NSCollectionToString(set2));
//把一个元素追加到set1后面,然后把新生成的集合赋值给set1
set1 = [set1 setByAddingObject: @"Struts 2.1权威指南"];
NSLog(@"添加一个元素后:%@", NSCollectionToString(set1));
//使用NSSet集合想集合set1中添加多个元素,相当于两个集合的交集
NSSet* s = [set1 setByAddingObjectsFromSet: set2];
NSLog(@"set1集合与set2集合的并集:%@", NSCollectionToString(s));
//计算两个集合是否有交集
BOOL b = [set1 intersectsSet:set2];
//将输出代表yes的1
NSLog(@"set1和set2是否有交集:%d", b);
//判断set1是否包含set2
BOOL bo = [set1 isSubsetOfSet: set2];
//将输出代表no的0
NSLog(@"set2是否是set1的子集:%d", bo);
//判断集合是否包含指定元素
BOOL bb = [set1 containsObject: @"疯狂Android讲义"];
//将输出代表yes的1
NSLog(@"set1中是否包含疯狂Android讲义: %hhd", bb);
//下面两行代码将会取出相同的的元素但是取出那个元素不确定
NSLog(@"set1取出一个元素:%@", [set1 anyObject]);
NSLog(@"set1取出一个元素:%@", [set1 anyObject]);
//使用代码块对集合元素进行过滤
NSSet* filteredSet = [set1 objectsPassingTest: ^(id obj, BOOL *stop) {
return (BOOL) ([obj length] > 8);
}];
NSLog(@"set1中元素的长度大于8的集合元素有:%@", NSCollectionToString(filteredSet));
}
return 0;
}
代码运行结果如下:
2.NSMutableSet的功能与用法
NSMutableSet继承了NSSSet,它代表了一个集合元素可变的NSSet集合,并且NSMutableSet在NSSet的基础上还增加了对于集合交集,并集,差集的方法。
下面代码示范了NSMutableSet集合的用法:
#import <Foundation/Foundation.h>
//把集合转换为字符串
NSString* NSCollectionToString (id array) {
NSMutableString* result = [NSMutableString stringWithString:@"["];
for (id object in array) {
[result appendString: [object 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 {
//创建一个初始化容量为10的集合
NSMutableSet* set = [NSMutableSet setWithCapacity:10];
[set addObject:@"赖晨煜"];
NSLog(@"添加一个元素后:%@", NSCollectionToString(set));
[set addObject: [NSArray arrayWithObjects:@"孙悟空", @"猪八戒", @"白龙马", nil]];
NSLog(@"添加了3个元素之后:%@", NSCollectionToString(set));
[set removeObject:@"猪八戒"];
NSLog(@"删除了1个元素之后:%@", NSCollectionToString(set));
//在此创建一个一个NSSet集合
NSSet* set2 = [NSSet setWithObjects:@"猪八戒", @"疯狂iOS讲义", nil];
//计算两个集合的并集
[set unionSet:set2];
NSLog(@"%@", NSCollectionToString(set));
//计算两个集合的差集
[set minusSet:set2];
NSLog(@"%@", NSCollectionToString(set));
//计算两个集合的交集
[set intersectSet:set2];
NSLog(@"%@", NSCollectionToString(set));
//用set2的值覆盖set的值
[set setSet:set2];
NSLog(@"%@",NSCollectionToString(set));
}
return 0;
}