美文网首页object c 基础语法iOS Developer
IOS学习笔记之Object-C(三)

IOS学习笔记之Object-C(三)

作者: 南山伐木 | 来源:发表于2017-02-25 18:37 被阅读54次

    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(三)

    相关文章

      网友评论

        本文标题:IOS学习笔记之Object-C(三)

        本文链接:https://www.haomeiwen.com/subject/rnrnwttx.html