OC语法<4.2>:Foundation框架中的集合类-NSArray

时间:2022-09-03 14:15:28

一:集合类                                                                                                                     

集合类的概述:        OC集合类有NSArray,NSMutableArray,NSDictionary,NSMutableDictionary,NSSet,NSMutableSet都是以面向对象的方式来 操作数组的,而且OC数组不想C语言中的数组只能存放一种数据类型,它可以存放任意类型的对象(注意是对象,本质是地址)
但是不能存放nil和非OC对象类型(基本数据类型int ,struct,enum等)如果有时候又非得存,就必须先将基本数据类型包装成对象

类型然后再用集合类进行存储,OC中提供的包装类是:NSNumber,NSValue。其中NSNumber继承于NSValue(NSNumber主要

针对于基本数据类型的包装,NSValue主要针对结构体进行包装),将包装成NSNSNumber或NSValue对象类型后存放到数组中,

然后从结合类中取出NSNumber,NSValue对象再转换成为基本数据类型。


NSArray 数组,NSDictionary 字典,NSSet 集合通称为集合类,都是用来打包数据,打包对象的。具有的功能包括: 1:增加、删除、插入、取出等功能 2:他是一个类文件,能够创建一个对象 3:遍历集合 4:排序功能

二:NSArray数组                                                                                                         

内容简介:

①:创建一个数组(包括快捷创建方式)

②:从数组中取出对象

③:判断数组中是否存在某对象

详细介绍和代码如下:

#import <Foundation/Foundation.h>
#import "Person.h"

int main(int argc, const char * argv[]) {
@autoreleasepool {
{
//1:创建一个数组
//NSArray 是不可变数组,一旦创建完成就不能对数组进行添加删除等操作。

NSArray *array = [[NSArray alloc]init];//这个就没有意义

//2:通过构造方法的方式创建一个NSArray
//在创建一个NSArray的时候集合最后一个元素一定是nil,因为nil代表集合的元素结束
NSArray *array1 = [NSArray arrayWithObjects:@"1",@"2",@"3",nil];
NSLog(@"array1元素为:%@",array1);

//3:数组中可以存储不同类型的对象
NSNumber *num = [NSNumber numberWithInt:20];//包装类,因为基本数据类型不能存入数组
NSArray *array2 = [NSArray arrayWithObjects:@"hello",@"2",num,nil];
NSLog(@"array2的元素为:%@",array2);

//4:数组中存储的实际是对象的地址,同样也可以存储数组的地址
NSArray *a1 =[[NSArray alloc]initWithObjects:array1,array2,nil];
NSLog(@"a1的元素为:%@",a1);//结果是两个数组

//5:存储自定义对象
//要重写descripton方法,不然打印的会是地址

Person *p1 = [[Person alloc]initWithName:@"rwy" andAge:24];
Person *p2 = [[Person alloc]initWithName:@"dwq" andAge:20];
Person *p3 = [[Person alloc]initWithName:@"xz" andAge:24];

NSArray *array3 = [[NSArray alloc]initWithObjects:p1,p2,p3 ,nil];
NSLog(@"array3的元素为:%@",array3);
//6:数组中存储基本数据类型
//注意不要把nil存储到NSArray 中,会导致数据丢失
NSString *str2 = nil;
NSArray *array4 = [NSArray arrayWithObjects:@"rwy",
[NSNumber numberWithInt:3],str2,@"2",nil];
NSLog(@"array4元素为 %@",array4);//结果为(rwy,3);
//7:创建数组的快捷方式(这个挺好用)

NSArray *array5 = @[@"r",@"w",@"y",[NSNumber numberWithInt:6]];
NSLog(@"array为:%@",array5);

//8:快速获得一个数组中的元素
NSString *arr = array5[3];
NSLog(@"获得的元素为:%@",arr);
}
#pragma mark 从集合中取出对象

{
//9从集合中取出数据
NSArray *array6 = @[@"r",@"w",@"y"];
NSString *str = [array6 objectAtIndex:2];
NSLog(@"str的第三个元素为:%@",str);
//10获得元素的个数
int a = [array6 count];
NSLog(@"元素个数为:%d",a);

}

#pragma mark 判断数组中是否存在某个对象
{
Person *p1 = [[Person alloc]initWithName:@"renwenyi" andAge:24];
Person *p2 = [[Person alloc]initWithName:@"duwaqing" andAge:24];

NSArray *array7 = @[p1,p2];
BOOL isContain = [array7 containsObject:p2];
if (isContain ) {
NSLog(@"该对象存在");
}else
{
NSLog(@"该对象不存在");
}

}

}
return 0;
}
附带的.m文件如下:

#import "Person.h"

@implementation Person
-(id)initWithName:(NSString *)name andAge:(int)age
{
if (self = [super init]) {
_name = name;
_age = age;

}
return self;
}

-(NSString *)description
{
return [NSString stringWithFormat:@"age= %d name= %@",_age,_name];
}

@end

三:数组的遍历                                                                                                            

内容简介:

①:for循环遍历 ②:增强for循环遍历 ③:枚举器遍历 详细介绍和代码如下:
#import <Foundation/Foundation.h>

int main(int argc, const char * argv[]) {
@autoreleasepool {
//1:创建数组,并用for循环遍历
NSArray *array = @[@"hello",@"every",@"one"];
NSUInteger count = array.count;
for (int i = 0; i< count; i++) {
NSString *str = array[i];
NSLog(@"array[%i]:%@",i,str);
}
/* 重点!!!!!!!
OC中的基本数据类型 char , int ,float,double
OC中增加的数据类型 id, BOOL, NSObject * (对象类型),block, SEL
C语言中的流程控制语句 if else while for
OC中增加的流程控制语句:增强for循环,格式如下

for (NSObject *obj in array)
{

}

array 代表你要存储的集合
in 代表你要取出的东西在那个集合里面
NSObject *obj 代表你的集合里面取出来的元素是什么类型的(obj代表任何类型),然后存储到obj中
*/

//2:使用增强for循环遍历数组
//不需要再定义array.count了,你的array.count是多少,它就自动循环多少次

for (NSString *str2 in array) {
//每一次都取出数组中的一个元素存储到str中
NSLog(@"array 元素为:%@",str2);
}

/*注意:
如果你的数组中存储了多种数据类型的数据,那么最好不要调用某个对象特有的方法,会导致系统崩溃
在实际的开发当中,往往一个数组只存储一种数据类型的数据
Person *p = [[Person alloc]init];
NSArray *array2 = @[@"hello",p,[NSNumber numberWithInt:10]];
for(NSString *str in array2)
{
NSLog(@"array3 中的str %@",str);//可能会报错
NSLog(@"str %ld",str.length); //会报错
}
//实际开发中这样用
//NSarray peronArray = a[];
*/
//3:枚举器遍历
NSArray *array3 = @[@"hello",@"every",@"body"];
//array3中所有的值就都存到枚举器当中了
NSEnumerator *enumerator = [array3 objectEnumerator];
//用while循环取出
NSString *value;
while (value = [enumerator nextObject]) {
NSLog(@"array3的元素为:%@",value);
}
}
return 0;
}

四:数组的排序                                                                                                                                    

简介:

①:使用storedArrayUseingSelector排序 ②:使用block类型排序 ③:对自己创建的对象进行排序 ④:根据sortedArrayUsingComparator也可以对自己创建的对象类型进行排序 详细介绍和代码如下:
#import <Foundation/Foundation.h>
#import "Person.h"

int main(int argc, const char * argv[]) {
@autoreleasepool {
//1:使用storedArrayUseingSelector排序,这是最简单的

//数组是有序数列,你怎么存进去,它就怎么排
NSArray *array = @[@"r",@"w",@"y",@"a"];
NSLog(@"排序前array 为:%@",array);
//compare:是系统默认的排序方法
NSArray *array1 = [array sortedArrayUsingSelector:@selector(compare:)];
NSLog(@"排序后array 为:%@",array1);
//[array sortedArrayUsingSelector:@selector(compare:)] 这个顺序肯定是没有变的,因为array
//是个不可变数组,这个方法的本质是给我们返回了一个新的NSArray,所以要传给一个新对象

//2:使用block类型排序
NSArray *array2 = @[@"c",@"8",@"b",@"4"];
NSLog(@"排序前array2 为:%@",array2);

array2 = [array2 sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
return [obj1 compare:obj2];//相当于下面两句
//NSComparisonResult result = [obj1 compare:obj2]
//return result;
//[obj1 compare:obj2]正序
//[obj2 compare:obj1]倒叙
}];
NSLog(@"排序后array2 为:%@",array2);


//3:对自己创建的对象进行排序
//我们创建一个Person类,写一个构造方法
//-(id)initWithName:(NSString *)name andAge:(int)age andYear:(NSString *)year;
Person *p1 = [[Person alloc]initWithName:@"renwenyi" andAge:24 andYear:@"1990"];
Person *p2 = [[Person alloc]initWithName:@"duwanqing" andAge:23 andYear:@"1991"];
Person *p3 = [[Person alloc]initWithName:@"xi*" andAge:30 andYear:@"1980"];
NSArray *array3 = @[p1,p2,p3];
NSLog(@"排序前array3 为:%@",array3);//自己创建的对象打印要重写description方法

//注意:对象排序我们用到一个新类 NSSortDescriptor
//如果你给你自己定义的属性进行排序,那么就必须根据某一个属性来进行排序
//NSSortDescriptorWithKey 就是表示你要根据那个属性排序就把那个属性的名字当作key传进去
//ascending 表示是按照正序还是倒叙,YES表示正序,NO表示倒叙
NSSortDescriptor *d1 = [NSSortDescriptor sortDescriptorWithKey:@"age" ascending:YES];
NSSortDescriptor *d2 = [NSSortDescriptor sortDescriptorWithKey:@"year" ascending:YES];

//如果按照多个属性进行排序,它会按照你传入的顺序分配优先级,本例就是先按照d2,再按照d1进行排序
NSArray *nsa = @[d2,d1];
array3 = [array3 sortedArrayUsingDescriptors:nsa];
NSLog(@"排序后array3 为:%@",array3);

//4:根据sortedArrayUsingComparator 也可以对自己创建的对象类型进行排序
NSArray *array4 = @[p1,p2,p3];
NSLog(@"排序前 array4 = %@",array4);
array4 = [array4 sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
Person *p1 =obj1;
Person *p2 = obj2;
return [p1.year compare:p2.year];
}];
NSLog(@"排序前后 array4 = %@",array4);
}
return 0;
}
Person的.h文件
#import <Foundation/Foundation.h>

@interface Person : NSObject

@property (nonatomic,strong)NSString *name;
@property (nonatomic,assign)int age;
@property (nonatomic,strong)NSString *year;

-(id)initWithName:(NSString *)name andAge:(int)age andYear:(NSString *)year;
//下面是类方法格式
//+(id)personWithName:(NSString *)name andAge:(int)age andYear:(NSString *)year;
@end
Person的.m文件
#import "Person.h"

@implementation Person

-(id)initWithName:(NSString *)name andAge:(int)age andYear:(NSString *)year
{
if (self = [super init]) {
_age = age;
_name = name;
_year = year;
}
return self;
}

-(NSString *)description
{
return [NSString stringWithFormat:@"name = %@ age = %i year = %@",self.name,self.age,self.year];
//相当于_name,_age,_year,调用self相当于调用了自己的get方法
}
@end

五:可变数组-NSMutableArray                                                                                                         

内容简介:

①:创建一个NSMutableArray可变数组 ②:在数组中删除一个或者多个元素 ③:可变数组的遍历,包括:for循环遍历,增强for循环遍历,枚举器遍历
#import <Foundation/Foundation.h>

int main(int argc, const char * argv[]) {
@autoreleasepool {

//NSMutableArray 继承自NSArray
//1:创建一个NSMutableArray可变数组
NSMutableArray *array = [[NSMutableArray alloc]initWithCapacity:0];

//使用addObject 动态给数组中添加元素
[array addObject:@"one"];
[array addObject:@"two"];
[array addObject:@"three"];
[array addObject:@"one"];
/*
注意!!!!!!
最后这个one添加的并不是新对象,工作原理,先把字符串放入到stringPool池子当中,当你添加一个新元素的时候
它会首先再池子里面找有么有这个对象,如果有的话就直接拿过来用,不需要再重新创建一个对象了,也是为了
节省内存,所以数组中就可以存储同一个对象多次
*/

//2:在数组中插入一个元素
[array insertObject:@"one" atIndex:2];

//3:删除元素,会删除数组中所有的同一个地址的对象
[array removeObject:@"one"];
//这样数组里面就没有"one"这个元素了

//4:通过索引的方式删除,如果删除的时候超出了数组的count值,那么就会导致异常(index beyond bounds)
[array removeObjectAtIndex:0];

//5:删除数组中所有的元素
[array removeAllObjects];

[array addObject:@"one"];
[array addObject:@"two"];
[array addObject:@"three"];
NSLog(@"arry 为 %@",array);


//数组的遍历
//1⃣️:for循环遍历
for (int i = 0 ; i< array.count; i++) {
NSString *str = [array objectAtIndex:i];
//注意!!!!!
//在数组遍历的时候,千万不要给数组中添加或者删除元素
//[array removeObject:@"one"];
NSLog(@"array 数组的第 %i 个一元素为:%@",i,str);
}

//2⃣️:增强for循环遍历
for (NSString * str1 in array) {
//中间也删除会报错(遍历那个数组的时候不要删除那个数组中的元素,请您记住!!!!)
NSLog(@"arry数组元素为:%@",str1);
}

//3⃣️:枚举器遍历
NSEnumerator *enumerator = [array objectEnumerator];
NSString *value;
while (value = [enumerator nextObject]) {
//中间写删除方法也会报错
NSLog(@"array 数组的元素分别为:%@",value);
}

//思考???:如果我们想要通过循环的方式找到某些元素,然后删除怎么办?

//我们可以通过一个中间变量来接收这些元素,然后通过删除中间变量来删除
//本例中我们想找到数组中是5的元素然后删除
NSMutableArray *array3 = [[NSMutableArray alloc]init];
[array3 addObject:@"1"];
[array3 addObject:@"2"];
[array3 addObject:@"3"];
[array3 addObject:@"4"];
[array3 addObject:@"5"];
NSMutableArray *temp = [[NSMutableArray alloc]init];
//[temp addObject:<#(id)#>]
for (NSString * strr in array3) {
if ([strr isEqualToString:@"5"]) {
[temp addObject:strr];
}
}

NSLog(@"删除5之前array3为:%@",array3);
NSLog(@"删除5之前temp为:%@",temp);
//①遍历临时数组进行删除
for (int i = 0; i<temp.count; i++) {
NSString *str3 = [temp objectAtIndex:i];
[array3 removeObject:str3];
//重点!!!!!!!!!!
//注意:这个循环里面为什么可以删除?因为删除的不是同一个数组,我们遍历的是temp数组,而删除的是array3数组

}
//②直接删除
//[temp removeAllObjects];
NSLog(@"删除5之后array3为:%@",array3);
}
return 0;
}