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(无顺序) [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(三)
新闻热点
疑难解答