NSArray
有顺序;固定的,一旦创建,里面的元素不可变;只能放OC的对象(且任何OC的对象都能放入);不能放nil(有特殊意义,代表数组结束);
创建:
NSArray *array = [NSArray array]; //创建一个空数组
[NSArray arrayWithObject:@"123"];//创建一个带1个元素的数组
[NSArray arrayWithObjects:@"123",@"345", nil];//创建一个带多个元素的数组,nil表示数组结束
方法:
[array count]:返回数组中元素个数
[array containsObject:@“123”]:判断是否包含了某个元素;
[array lastObject]:返回数组的最后一个元素;
[array objectAtIndex:1]:返回在index=1处的元素
[array indexOfObject:@“345”]:返回元素在数组中的位置
[array isEqualToArray:array]:判断两个数组里的元素是否相同
[array makeObjectsPerformSelector:@selector(length)]:让元素内所有的元素都调用一次元素的方法(这里是str的length方法);
可带参数:withObject:执行的方法可带一个参数(但最多只能带一个参数);
[array arrayByAddingObject:@“3”]:添加一个元素,返回一个新数组,原数组array不变;
[array arrayByAddingObjectsFromArray:array2]:将两个数组合并,返回一个新的数组,原数组都不变;
array3 subarrayWithRange:NSMakeRange(1, 2):截取指定范围和长度的元素,返回一个新的数组
[array componentsJoinedByString:@“,”]:用指定的分隔符拼接所有的元素,返回一个拼接后的字符串
[array writeToFile:@"/Users/sionfan/work/aaa.xml" atomically:YES];//将数组写入到文件中;
[NSArray arrayWithContentsOfFile:path]://从文件中读取一个数组,但文件中的格式必须是和生成的的格式一样的xml
— 排序 -
[array sortedArrayUsingSelector:@selector(compare:)]:返回一个排好序的新数组,原数组的内容顺序都不会改变;会使用对象的指定的方法进行排序;(同java,需要在对象的类中实现一个比较方法,如-(NSComparisonResult)compareStudent:(Student *)stu;);
利用block排序sortedArrayUsingComparator,(同java)需要修改自动生成的方法的形参名:
//利用block进行排序
NSArray *stus3 = [stus sortedArrayUsingComparator:^NSComparisonResult(Student *obj1, Student *obj2) {
//先按姓排序
NSComparisonResult result = [obj1.lastName compare:obj2.lastName];
if (result == NSOrderedSame) {
//姓相同
result = [obj1.fistName compare:obj2.fistName];
}
return result;
}];
— 多条件排序 sortedArrayUsingDescriptors:desces—
//先按书名排序,对应上student类中book.bookName的名字;
NSSortDescriptor *bookDesc = [NSSortDescriptor sortDescriptorWithKey:@"book.bookName" ascending:YES];
//再按姓进行排序
NSSortDescriptor *lastDesc = [NSSortDescriptor sortDescriptorWithKey:@"lastName" ascending:YES];
//再按名进行排序
NSSortDescriptor *firstDesc = [NSSortDescriptor sortDescriptorWithKey:@"firstName" ascending:YES];
//顺序添加排序描述器到数组
NSArray *desces = [NSArray arrayWithObjects:bookDesc,lastDesc,firstDesc, nil];
NSArray *stus5 = [stus sortedArrayUsingDescriptors:desces];
@[@“,@“””];可直接创建一个数组,但是不可变数组(NSArray)
++ 遍历(4种方式) +
for(int i;i<count;i++){id obj = [array objectAtIndex:i]};
for(id *str in array){..str..};//快速遍历
[array enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
//id obj:遍历到的对象
//idx :遍历到的位置
//stop:是否要中止遍历;*stop = YES;//加*才能改变外面的bool值
NSLog(@"%@,%i",obj,idx);
}];
迭代器遍历
//迭代器遍历,先产生一个迭代器
//正向迭代器
// NSEnumerator *enumerator = [array objectEnumerator];
//返序迭代器,从末尾迭代
NSEnumerator *enumerator = [array reverseObjectEnumerator];
//获取下一个需要遍历的元素
id obj = nil;
while(obj = [enumerator nextObject]){
NSLog(@"%@",obj);
};
//返回迭代器中所有元素组的一个数组,只取出没有遍历过的对象,所有在while遍历后为空
NSArray *array2 = [enumerator allObjects];
+NSMutableArray 继承自NSArray,可变数组
实现所有NSArray的方法;
增加add**,insert**,replace**及remove**方法;[调用一次add**方法会调用元素retain操作,计数器值+1;调用一次remove**方法会调用元素的release操作,计数器值-1;以此保证不会内存泄露]
[排序:由于可变,可直接对本数组进行排序,故对应的方法多了三个没有_ed的排序方法,可直接对原数组进行排序]
只能添加不为nil的OC对象
** 内存管理 **
当把一个对象塞进一个数组中时,这个对象的计数器会加1;
//当数组被销毁时,会对内部的所有元素都做一次release操作;
[array release];
- NSSet (同java中的set,不常用)
+NSDictionary字典,通过惟一的key找到对应的value(类似于java中的map)
NSDictionary是不可变的;一旦创建就不可再更改;不能放基本数据和nil;只能放OC对象;(key唯一)
— 创建 —
[NSDictionary dictionary]:
[NSDictionary dictionaryWithObject:@"v" forKey:@“key”];
[NSDictionary dictionaryWithObjectsAndKeys:@"v2",@"k1",@"v3",@"k2", nil];
[NSDictionary dictionaryWithContentsOfFile:path]:从一个文件读取并生成一个map;但必须先是生成格式的xml
[NSDictionary dictionaryWithObjects:objects forKeys:keys];
— 方法 —
[dict count]:有几个键值对;
[dict objectForKey:@“k1”]:通过key找value;但只能取,不能改;
[dict writeToFile:@"/Users/sionfan/work/ddd.txt" atomically:YES]; //将字典写入到一个文件中,也是生成一个xml文件;
[dict allKeys]:所有的key的NSArray(无顺序)
[dict allValues]:所有的value的NSArray(无顺序)
[dict3 objectsForKeys:[NSArray arrayWithObjects:@"k1",@"k2",@"k3", nil] notFoundMarker:@“notfound”];//用一组keys找一组values;notFoundMarker是没有的找到时的返回值,不能为nil;
[dict keysSorted*:]对keys进行排序;相当于对keys这个NSArray进行排序,方法也类似;
—遍历—
//1.循环遍历
for(id key in dict3){
NSLog(@"%@ = %@",key,[dict3 objectForKey:key]);
}
//2.迭代器遍历 key迭代器
NSEnumerator *keyEnumerator = [dict3 keyEnumerator];
//value迭代器
// NSEnumerator *valueEnumerator = [dict3 objectEnumerator];
id key = nil;
while (key = [keyEnumerator nextObject]) {
NSLog(@"%@ = %@",key,[dict3 objectForKey:key]);
}
//3.block迭代器遍历
[dict3 enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) {
//*stop=YES,停止遍历
NSLog(@"block %@ = %@",key,obj);
}];
— NSDictionary内存管理—同NSArray;在创建时对象引用+1;在调用remove**方法时会对remove的对象调用一次release操作;当dict销毁时也会对里面所有的key和value执行一次release操作(计数器值-1);
+NSMutableDictionary是NSDictionary的子类
增加修改类的方法
set**;add**;remove**;replace**
[void * 代表任何指针]
[在对json数据解析时,若数据的值为null或为空;则不会创建这个键值对]
+NSValue
用于包装结构体,也能包装任意类型(包装基本类型)。
包装:valueWith**:
解包:**Value:
对于自定义的结构体:
Date date = {1999,9,12};
char *type = @encode(Date);//根据结构体类型生成对应的类型描述字符串
NSValue *dateValue = [NSValue value:&date withObjCType:type];
//取出时,先定义一个结构体
Date d2 ;
//取出放入的值
[dateValue getValue:&d2];
//取出放入的objcType
[dateValue objCType];
+NSNumber继承自NSValue
由于字典和数组不能放入基本数据,故需要转换;这里可用NSNumber来包装。但不像java那样自动打包解包;放入什么,取出来就是什么;(但只能包装基本数据,不能包装结构体)
初始化:
numberWith**(基本类型:)
还原成基本类型:init**;
+NSNull
由于集合中不能放空(nil);为了达到能放入一个空值,就使用NSNull。是一个OC对象。
创建:只有一个方法 [NSNull null]:
是单例的(所有的对象指向的都是同一块地址)
++ NSDate ++时间相关
//NSData,是一个字节数组(类似于Java中的byte[]);
//NSDate才是时间
NSDate *date = [NSDate date];//返回当前时间
NSLog(@"%@",date);
//单位是秒,IOS中的时间都是以秒为单位
date = [NSDate dateWithTimeIntervalSinceNow:10];//以当前时间+10
NSLog(@"%@",date);
date = [NSDate dateWithTimeIntervalSince1970:100];//以70-1-1年的时间开始增加,将long型毫秒值转成Date
NSLog(@"%@",date);
date = [NSDate distantFuture];//随机的返回一个将来的时间
date = [NSDate distantPast];//随机的返回一个过去的时间
NSTimeInterval interval = [date timeIntervalSinceReferenceDate];//返回毫秒数long
// [date timeIntervalSince1970];//返回当前时间的毫秒值
// [date isEqualToDate:[NSDate date]];//比较两个时间是否相同
// [date earlierDate:date1];//返回比较早的那个时间
// [date laterDate:date1];//返回比较晚的那个时间
//时间格式化
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
formatter.dateFormat = @"yyyy-MM-dd hh:mm:ss";
NSString *time = [formatter stringFromDate:date];//将日期转换成string
time = @"2016-02-03 10:23:30";
date = [formatter dateFromString:time];//将string转换成日期
NSCalendar *calender = [NSCalendar currentCalendar];//类似于Java中 Calender
+NSObject与反射
id stu = [Student new];
//isKindOfClass 判断对象是否属于某个类 或者 子类
if ([stu isKindOfClass:[Student class]]) {
NSLog(@"属于这个类");
}
//isMemberOfClass 判断对象是否属于某个类(但不包括子类)
if([stu isMemberOfClass:[Student class]]){
NSLog(@"属于这个类");
}
//间接调用对象的方法,还要带其他参数
// [stu performSelector:@selector(test)];
//延迟调用,在IOS中才有用,main是循环的,才能执行,在命令行的项目中,main只有一次,不能延迟
// [stu performSelector:<#(nonnull SEL)#> withObject:<#(nullable id)#> afterDelay:<#(NSTimeInterval)#>]
//其他线程调用对象的方法
// [stu performSelectorOnMainThread:<#(nonnull SEL)#> withObject:<#(nullable id)#> waitUntilDone:<#(BOOL)#>]
+反射
//反射,通过字符串生成一个对象
NSString *str = @"Student";
Class class = NSClassFromString(str);
//类的反射
Student *stu = [[class alloc] init];
//Class 变成字符串
// NSString *name = NSStringFromClass([Student class]);
NSLog(@"%@",stu);
//方法的反射
NSString *method = @"test";
//得到方法
SEL selector = NSSelectorFromString(method);
//执行方法
[stu performSelector:selector];
//将SEL转化为字符串
NSString *selectorName = NSStringFromSelector(selector);
+copy
目的:就是对一个对象和集合的拷贝,改变副本不影响原对象(同java中的clone)。
创建不可变副本(copy):要先实现NSCopying协议,创建的是不可变副本(NSString,NSArray);
创建可变副本(mutableCopy),要实现NSMutableCopying协议,用于创建可变副本(NSMutableString,NSMutableArray);
深拷贝(mutableCopy,内容拷贝):是会产生一个新的对象,是真正的拷贝,从内存中拷贝出一份,并指向它。新对象的计数器值为1,原对象的计数器值不变。
浅拷贝(copy):只是简单的指针拷贝(地址拷贝)。如对于如NSString的对象,由于这类对象本身不可改变,为了性能提升,故copy方法不会创建一个新的对象,是将原对象本身返回,且原对象的计数器+1(相当于retain操作)
[两者区别是有没有产生新对象;但还有特殊情况,是NSMutableString str=..;NSString *str2 = [str copy];
//可变对象 ——> 不可变对象 和 不可变对象 ——> 可变对象,由于拷贝出的对象与原对象的结构都不一样,所以不能简单的指针拷贝,故是深拷贝。(只有一种情况:不可变—copy—>不可变才是浅拷贝)]
在定义对象时用copy: @property (nonatomic,copy) NSString *lastName;//修改外面的变量,不会影响到内部的成员变量(对于固定的NSString一般用copy,不允许随便修改)
则代表在set方法中,会release旧对象,copy新对象:[_lastName release];_lastName = [lastName copy];
在外面用操作mutable时,就不会改变对象中的值:NSMutableString *string = …; stu.lastName = string;//赋值; [string appendString@“..”];//改变赋值的字符串,则不会改变对象中的字符串的值。(用retain,则对象中的值会改变)
使用copy时,建议使用[self class]代替类名;
[子类继承父类,在构造方法时,实例化使用Student *stu = [[[self class] alloc] init];//让子类来调用父类的方法,不然父类可能调用到子类的方法,出现找不到方法的错误]
博客地址:IOS学习笔记之Object-C(三)