Foundation框架学习

Foundation 框架详解

字符串

字符串的类型主要有两种,NSString代表不可变的字符串,NSMutablestring代表可变的字符串;两种类的方法往往具有一定的相似之处

创建字符串

首先从NSString下手
其功能如下:
在这里插入图片描述
接下来将使用三种方法创建一个NSString类的对象

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        unichar data[6] = {97, 98, 99, 100, 101, 102};
        NSString* str1 = [[NSString alloc]initWithCharacters:data length:6];
        NSLog(@"%@",str1);
        char* cstr = "Hello,iOS";
        NSString* str2 = [NSString stringWithUTF8String:cstr];//将c中的char型字符串转换为nSString类的字符串
        NSLog(@"%@",str2);
        [str2 writeToFile:@"myFile.txt" atomically:YES encoding:NSUTF8StringEncoding error:nil];
        NSString* str3 = [NSString stringWithContentsOfFile:@"myFile.txt" encoding:NSUTF8StringEncoding error:nil];
        NSLog(@"%@",str3);
        }
    return 0;
}

第一种方法将数组中的数字转换为字符串,第二种将c种的字符串转化为NSString,第三种将文件中的字符串转换为NSString,此时会自动创建一个文件;

NSString的常用功能

以下是一些方法的使用

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSString* str = @"Hello";
        NSString* book = @"《疯狂iOS讲义》";
        str =[str stringByAppendingString:@",iOS"];
        NSLog(@"%@",str);
        const char* cstr = [str UTF8String];
        NSLog(@"%s",cstr);
        str = [str stringByAppendingFormat:@"%@是一本非常不错的图书",book];
        NSLog(@"%@",str);
        NSLog(@"字符数%lu",[str length]);//返回字符数
        NSLog(@"编码后的字节数%lu",[str lengthOfBytesUsingEncoding:NSUTF8StringEncoding]);//以何种方法编码后返回字节数
        NSString* s1 = [str substringToIndex:10];//返回从哪里结束的字符串
        NSString* s2 = [str substringFromIndex:5];//返回从哪里开始的字符串
        NSString* s3 = [str substringWithRange:NSMakeRange(5, 10)];//返回那个区间内的字符串
        //NSMakeRange是一个返回NSRange结构体的函数
        NSLog(@"%@ %@ %@",s1,s2,s3);
        NSRange pos = [str rangeOfString:@"iOS"];
        NSLog(@"%lu %ld",pos.location,pos.length);
        str = [str uppercaseString];//将字符串中的小写转换为大写
        NSLog(@"%@",str);
    }
    return 0;
}

由于书上有详细的说明,为直接搬照书上的来了
在这里插入图片描述

注意一下代码种NSRange的解释

可变字符串

NSMutablestring类的对象字符串是可变的,即调用方法改变字符串时是改变对象本身,而不是像NSString是创建一个新的对象;
大部分方法与NSString类似,这里不做详细说明,可以参考书上的
在这里插入图片描述
以下是我的实现

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSString* book = @"《疯狂iOS讲义》";
        NSMutableString* str = [NSMutableString stringWithString:@"Hello"];
        [str appendString:@",iOS!"];//在尾部增加
        NSLog(@"%@",str);
        [str appendFormat:@"%@是一本非常不错的图书。",book];
        NSLog(@"%@",str);
        [str insertString:@"fkit.org" atIndex:6];//向某一位置插入一个字符串
        NSLog(@"%@",str);
        [str deleteCharactersInRange:NSMakeRange(6, 12)];//删除某一区间内的字符串
        NSLog(@"%@",str);
        [str replaceCharactersInRange:NSMakeRange(6, 9) withString:@"Object-C"];//将某一字符串取代某一区间内的字符
        NSLog(@"%@",str);
    }
    return 0;
}

注意一下NSmakeRange(6,12)指的是6后面的12个字符;
第一个6是赋给NSrange结构体中的location,第二个12是赋给length
还有个规律就是NSMutablestring调用改变自身对象时的方法都不是以string开头,而NSString这些方法往往以string或substring开头,往往方法所需的形参和作用在方法名中有所体现;

日期和时间

日期和时间(NSDate)

NsDate一般包括两种创建对象的方法,其中类方法以date开头,实例方法以init开头;常见的方法参考书上的
在这里插入图片描述

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSDate* data2 = [[NSDate alloc]initWithTimeIntervalSinceNow:3600*24];
        NSDate* data3 = [[NSDate alloc]initWithTimeIntervalSinceNow:-3*3600*24];
        NSDate* data1 = [NSDate date];
        NSDate* data4 = [NSDate dateWithTimeIntervalSince1970:3600*24*366*20];
        //初始化方法,实例方法init开头,类方法date开头
        NSLog(@"%@",data1);
        NSLog(@"%@",data2);
        NSLog(@"%@",data3);
        NSLog(@"%@",data4);
        NSLocale* cn = [NSLocale currentLocale];//NSLocale代表一个语言,国际环境;
        NSLog(@"%@",[data1 descriptionWithLocale:cn]);//在某一环境下进行描述
        NSDate* earlier  =[data1 earlierDate:data2];//取早的
        NSDate* later = [data1 laterDate:data2];
        switch ([data1 compare:data3]) {
            case NSOrderedAscending:
                NSLog(@"前早于后");
            case  NSOrderedSame:
                NSLog(@"前等于后");
            case  NSOrderedDescending:
                NSLog(@"前晚于后");
        }
        NSLog(@"%g",[data1 timeIntervalSinceDate:data3]);//比较时间,返回deable类型;
        NSLog(@"%g",[data2 timeIntervalSinceNow]);
    }
    return 0;
}

需要注意的点:
NSLocale是一种代表语言和国际环境的类;
compare方法是NSObjective的方法,因此所有的类都有这个方法,该方法如果前者大于后者,会返回NSOrderedDescending,反之返回NSOrderAscending,相同则会返回NSOrderedSame;

日期格式器(NSDateFormatter)

使用步骤:
先创建一个NSDateFormatter对象,然后对该对象调用setDateStyle和set Timestyle方法格式化日期和时间风格,也可以调用setNSDateFormate方法实现自定义风格;最后通过NSDateFormatter对象调用stringFromdate或dateFrom string实现转换;
在这里插入图片描述

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSDate* dt = [NSDate dateWithTimeIntervalSince1970:3600*24*366*20];
        NSLocale* locales[] = {[[NSLocale alloc]initWithLocaleIdentifier:@"zh_CN"],[[NSLocale alloc]initWithLocaleIdentifier:@"en_US"]};
        NSDateFormatter* df[8];
        for (int i = 0; i < 2; i++) {
            df[i*4] = [[NSDateFormatter alloc]init];
            [df[i*4] setDateStyle:NSDateFormatterShortStyle];
            [df[i*4] setTimeStyle:NSDateFormatterShortStyle];
            [df[i*4] setLocale:locales[i]];
            df[i*4+1] = [[NSDateFormatter alloc]init];
            [df[i*4+1] setDateStyle:NSDateFormatterMediumStyle];
            [df[i*4+1] setTimeStyle:NSDateFormatterMediumStyle];
            [df[i*4+1] setLocale:locales[i]];
            df[i*4+2] = [[NSDateFormatter alloc]init];
            [df[i*4+2] setDateStyle:NSDateFormatterLongStyle];
            [df[i*4+2] setTimeStyle:NSDateFormatterLongStyle];
            [df[i*4+2] setLocale:locales[i]];
            df[i*4+3] = [[NSDateFormatter alloc]init];
            [df[i*4+3] setDateStyle:NSDateFormatterFullStyle];
            [df[i*4+3] setTimeStyle:NSDateFormatterFullStyle];
            [df[i*4+3] setLocale:locales[i]];
        }
        for (int i = 0; i < 2; i++) {
            switch (i) {
                case 0:
                    NSLog(@"中国日期格式");
                    break;;
                case 1:
                    NSLog(@"美国日期格式");
                    break;
            }
            NSLog(@"%@",[df[i] stringFromDate:dt]);
            NSLog(@"%@",[df[i+1] stringFromDate:dt]);
            NSLog(@"%@",[df[i+2] stringFromDate:dt]);
            NSLog(@"%@",[df[i+3] stringFromDate:dt]);
        }
        NSDateFormatter* df2 = [[NSDateFormatter alloc]init];
        [df2 setDateFormat:@"公元yyyy年MM月DD日HH时mm分"];
        NSLog(@"%@",[df2 stringFromDate:dt]);
        NSString* dateStr = @"2013-03-02";
        NSDateFormatter* df3 = [[NSDateFormatter alloc]init];
        [df3 setDateFormat:@"yyyy-MM-dd"];//
        NSDate* date2 = [df3 dateFromString:dateStr];
        NSLog(@"%@",date2);
    }
    return 0;
}

日历(NSCalendar)与日期组件(NSDateComponents)

NSCalendar的功能与NSDateFormatter的功能实现大体相似,我这里直接搬照书上的图了;
在这里插入图片描述
在这里插入图片描述

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSCalendar* gregorian = [[NSCalendar alloc]initWithCalendarIdentifier:NSCalendarIdentifierGregorian];//初始化一个日历,然后以它作为对象调用方法
        NSDate* date = [NSDate date];
        unsigned unitFlags = NSCalendarUnitYear |NSCalendarUnitMonth |NSCalendarUnitDay |NSCalendarUnitHour |NSCalendarUnitMinute |NSCalendarUnitSecond |NSCalendarUnitWeekday;//设置一个时间字段的旗帜,获取指定的信息,因为编译器的问题与书上有所不同
        NSDateComponents* comp =[gregorian components:unitFlags fromDate:date];
        NSLog(@"%ld %ld %ld %ld %ld %ld %ld",comp.year,comp.month,comp.day,comp.hour,comp.minute,comp.second,comp.weekday);
        //注意NSDateComponents中的信息都是数字的形式;
        NSDateComponents* comp2 =[[NSDateComponents alloc]init];
        comp2.year = 2013;
        comp2.month = 4;
        comp2.day = 5;
        comp2.hour = 18;
        comp2.minute = 34;
        NSDate* date2 = [gregorian dateFromComponents:comp2];
        NSLog(@"%@",date2);
    }
    return 0;
}

需要注意一下旗帜的树立和NSDateComponents中的实例变量都是数字;

对象复制

NSObjective类提供了copy和Mutablecopy方法实现对已有对象的复制,返回原始对象的副本;

copy和mutablecopy

两种方法都是返回原始对象的副本,只是一个返回不可变的副本,一个返回可变的副本;
改变副本不会对原始对象产生影响;在这里插入图片描述

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSMutableString* book = [NSMutableString stringWithString:@"疯狂iOS讲义"];
        NSMutableString* bookcopy = [book mutableCopy];
        [bookcopy replaceCharactersInRange:NSMakeRange(2, 3) withString:@"Android"];//改变副本不会改变原来的对象
        NSLog(@"%@ %@",book,bookcopy);
        NSString* str = @"fkit";
        NSMutableString* strcopy =[str mutableCopy];
        [strcopy appendString:@".org"];
        NSLog(@"%@ %@",str,strcopy);
        NSMutableString* strcopy2 = [str copy];
       // [strcopy2 appendString:@"aa"];//上面copy方法复制的是一个不可变副本,strcopy2实际上是NSmutablestring类的对象
    }
    return 0;
}

上面代码中的注释就是两者间的区别所在;

NSCopying和NsMutableCopy协议

当使用自定义的类进行复制时,不能直接调用copy和Mutablecopy,虽然NsObjective提供了copy和Mutablecopy方法,但这两种方法需要调用copyWithzone和mutablecopywithzone这两种NSObjective没有提供的方法,所以对自定义类的复制需要完成两部:该类要遵守NScopying或NSMutablecopy协议,并在实现部分实现上面的方法;

#import <Foundation/Foundation.h>
#import "FKDog.h"
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        FKDog* w = [[FKDog alloc]init];
        w.name = [NSMutableString stringWithString:@"旺财"];
        w.age = 20;
        FKDog* w2 = [w copy];//对自定义类的copy方法要是该类遵守NScopying协议并实现copywithzone方法,因为copy方法实际上调用了该方法;
        //w2.name = [NSMutableString stringWithString:@"大黄"];
        //w2.age = 30;
        [w2.name replaceCharactersInRange:NSMakeRange(0, 2) withString:@"sncopy"];//浅复制只是将地址复制过去,当改变副本中的值是,改变的是地址指向的那个值,因此原始对象会改变
        NSLog(@"%@ %d",w.name,w.age);
        NSLog(@"%@ %d",w2.name,w2.age);
    }
    return 0;
#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface FKDog : NSObject <NSCopying>
@property (nonatomic, strong) NSMutableString* name;
@property (nonatomic, assign) int age;
@end

NS_ASSUME_NONNULL_END

#import "FKDog.h"

@implementation FKDog
- (id)copyWithZone:(NSZone *)zone {
    NSLog(@"执行copywithzone");
    FKDog* w = [[[self class]allocWithZone:zone]init];
    w.name = self.name;
    //w.name = [self.name mutableCopy];//这里可以通过对NSMutablestring类调用复制方法复制一个新的对象,再让其指向这个副本实现深复制;
    w.age = self.age;
    return w;
}
@end

浅复制和深复制

看我上一节的代码,可以看见我在复制成员变量name是把地址直接赋给副本,所以副本的name实际还是指向原始对象中的name,在改变副本是,还是会改变原始对象;
而我上面注释的那部分则是深复制的实现,即对name进行一次NSMutableString或NsString类的复制;这时会创建一个新的对象和地址,就不会出现副本改变造成的原始对象改变;

setter方法的复制选项

在定义属性时,我们常常会使用copy指示符;copy指示符实际上是在setter方法中付给成员变量的值是通过copy方法复制的不可变副本,即该属性一定是不可变的,可以看书上的例子,代码忘了写了
在这里插入图片描述

数组(NSArray和NSMutableArray)

NSArray是一个可重复,有序,元素有对应索引的集合

NSArray的功能和作用

对于NSArray的方法,书上的很详细,所以直接展示书上的图了
在这里插入图片描述
在这里插入图片描述
代码实现如下:

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSArray* array = [NSArray arrayWithObjects:@"皮卡丘",@"杰尼龟",@"妙蛙种子",@"小火龙",@"伊布", nil];
        NSLog(@"%@ %@ %@",[array objectAtIndex:0],[array objectAtIndex:1],[array lastObject]);
        NSArray* arr1 = [array objectsAtIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(2, 3)]];
        NSLog(@"%@",arr1);
        NSLog(@"%ld",[array indexOfObject:@"小火龙"]);
        NSLog(@"%ld",[array indexOfObject:@"伊布" inRange:NSMakeRange(2, 1)]);//因为该对象的索引不在这个区间内,所以会返回NSNotFound的值;
        array = [array arrayByAddingObject:@"蒜头王八"];
        array = [array arrayByAddingObjectsFromArray:[NSArray arrayWithObjects:@"黄皮耗子",@"闪光大嘴雀", nil]];//array相当于一个不可变对象
        for (int i = 0; i < array.count; i++) {
            NSLog(@"%@",array[i]);
        }
        NSArray* arr2 = [array subarrayWithRange:NSMakeRange(5, 3)];
        [arr2 writeToFile:@"myFile.txt" atomically:YES];
    }
    //枚举器的使用
    NSArray* array = [NSArray arrayWithContentsOfFile:@"myFile.txt"];
    NSLog(@"%@",array);
    NSEnumerator* en = [array objectEnumerator];
    id object ;
    while (object = [en nextObject]) {
        NSLog(@"%@",object);
    }
    en = [array reverseObjectEnumerator];
    while (object = [en nextObject]) {
        NSLog(@"%@",object);
    }
    //快速枚举
    for (id object in array) {
        NSLog(@"快速枚举");
        NSLog(@"%@",object);
    }
    return 0;
}

以上需要注意的两点:
这里的NSArray是一种不可变类,在改变得到新的数组时,会创建一个新的对象;
[array objectsAtIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(2, 3)]];这里应用的方法其参数时NSIndexSet类的对象,所以要用其类方法创建对象,NSIndexSet是位置区间的集合;
NSArray的特点是可以通过索引找到对应的元素,方法的实现也具有该特点;
当直接输出该对象时,中文字符由于编码的问题会和平时有所不同;
还有NSArray判断查找的标准是isEqual返回yes;

#import <Foundation/Foundation.h>
#import "FKUser.h"
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSArray* array = [NSArray arrayWithObjects:[[FKUser alloc]initWithName:@"a" pass:@"1"], [[FKUser alloc]initWithName:@"b" pass:@"2"],[[FKUser alloc]initWithName:@"c" pass:@"3"], [[FKUser alloc]initWithName:@"d" pass:@"4"], [[FKUser alloc]initWithName:@"f" pass:@"5"], nil];
        FKUser* w = [[FKUser alloc]initWithName:@"c" pass:@"3"];
        NSUInteger pos = [array indexOfObject:w];
        NSLog(@"%ld",pos);//搜索时判断的是isequall是否为yes
        NSLog(@"%@",[w description]);
        [array makeObjectsPerformSelector:@selector(say:) withObject:@"NB!"];
        NSString* content = @"疯狂iOS讲义";
        [array enumerateObjectsAtIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(2, 2)] options:NSEnumerationReverse usingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {//倒序
            NSLog(@"正在处理%ld个对象%@",idx,obj);
            [obj say:content];
        }];
    }
    return 0;
}

对集合元素整体调用方法

这要有以下几种方法:
在这里插入图片描述
代码如下

#import <Foundation/Foundation.h>
#import "FKUser.h"
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSArray* array = [NSArray arrayWithObjects:[[FKUser alloc]initWithName:@"a" pass:@"1"], [[FKUser alloc]initWithName:@"b" pass:@"2"],[[FKUser alloc]initWithName:@"c" pass:@"3"], [[FKUser alloc]initWithName:@"d" pass:@"4"], [[FKUser alloc]initWithName:@"f" pass:@"5"], nil];
        FKUser* w = [[FKUser alloc]initWithName:@"c" pass:@"3"];
        NSUInteger pos = [array indexOfObject:w];
        NSLog(@"%ld",pos);//搜索时判断的是isequall是否为yes
        NSLog(@"%@",[w description]);
        [array makeObjectsPerformSelector:@selector(say:) withObject:@"NB!"];
        NSString* content = @"疯狂iOS讲义";
        [array enumerateObjectsAtIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(2, 2)] options:NSEnumerationReverse usingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {//倒序
            NSLog(@"正在处理%ld个对象%@",idx,obj);
            [obj say:content];
        }];
    }
    return 0;
}

主要可以归类于两种方法,一种使每一个元素调用指定的方法,另一种对每一个元素使用代码块进行操作;
注意一下代码块的格式和参数即可;
还要注意代码块中控制正序和倒序的参数即可
这两种方法也叫迭代方法;

对NSSarray进行排序

排序方法都是以sort开头的,具体可以分为三种

在这里插入图片描述
直接用元素自身的方法进行排序的方法叫自然排序,通过函数和代码块的方法排序叫定制排序。

#import <Foundation/Foundation.h>
NSInteger insort (id num1, id num2, void* context) {
    int v1 = [num1 intValue];
    int v2 = [num2 intValue];
    if (v1 > v2) {
        return NSOrderedDescending;
    }
    if (v1 < v2) {
        return NSOrderedAscending;
    }
    return NSOrderedSame;
}
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSArray* array1 = [NSArray arrayWithObjects:@"a",@"c",@"b",@"d",@"f", nil];
        array1 = [array1 sortedArrayUsingSelector:@selector(compare:)];
        NSLog(@"%@",array1);
        NSArray* array2 = [NSArray arrayWithObjects:[NSNumber numberWithInt:3],[NSNumber numberWithInt:5],[NSNumber numberWithInt:1],[NSNumber numberWithInt:6],[NSNumber numberWithInt:2], nil];
        array2 = [array2 sortedArrayUsingFunction:insort context:nil];
        NSLog(@"%@",array2);
        NSArray* array3 = [array2 sortedArrayUsingComparator:^NSComparisonResult(id  _Nonnull obj1, id  _Nonnull obj2) {
            int v1 = [obj1 intValue];
            int v2 = [obj2 intValue];
            if (v1 > v2) {
                return NSOrderedDescending;
            }
            if (v1 < v2) {
                return NSOrderedAscending;
            }
            return NSOrderedSame;
        }];
        NSLog(@"%@",array3);
    }
    return 0;
}

注意一下,这些方法需要的方法或函数,返回值都是NSOrderedxxx,代表大小;

使用枚举器遍历元素

枚举器指的是NSEnumerator类的对象,该对象可以调用方法来遍历集合中的元素,注意一下reverse代表倒序;
使用如下:

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSArray* array = [NSArray arrayWithObjects:@"皮卡丘",@"杰尼龟",@"妙蛙种子",@"小火龙",@"伊布", nil];
        NSLog(@"%@ %@ %@",[array objectAtIndex:0],[array objectAtIndex:1],[array lastObject]);
        NSArray* arr1 = [array objectsAtIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(2, 3)]];
        NSLog(@"%@",arr1);
        NSLog(@"%ld",[array indexOfObject:@"小火龙"]);
        NSLog(@"%ld",[array indexOfObject:@"伊布" inRange:NSMakeRange(2, 1)]);//因为该对象的索引不在这个区间内,所以会返回NSNotFound的值;
        array = [array arrayByAddingObject:@"蒜头王八"];
        array = [array arrayByAddingObjectsFromArray:[NSArray arrayWithObjects:@"黄皮耗子",@"闪光大嘴雀", nil]];//array相当于一个不可变对象
        for (int i = 0; i < array.count; i++) {
            NSLog(@"%@",array[i]);
        }
        NSArray* arr2 = [array subarrayWithRange:NSMakeRange(5, 3)];
        [arr2 writeToFile:@"myFile.txt" atomically:YES];
    }
    //枚举器的使用
    NSArray* array = [NSArray arrayWithContentsOfFile:@"myFile.txt"];
    NSLog(@"%@",array);
    NSEnumerator* en = [array objectEnumerator];
    id object ;
    while (object = [en nextObject]) {
        NSLog(@"%@",object);
    }
    en = [array reverseObjectEnumerator];
    while (object = [en nextObject]) {
        NSLog(@"%@",object);
    }
    //快速枚举
    for (id object in array) {
        NSLog(@"快速枚举");
        NSLog(@"%@",object);
    }
    return 0;
}

枚举器的大致使用的形式就是通过while循环和nextObject方法返回遍历元素;
上面还提到了快速枚举,这是更为常用和简洁的枚举方法,但本质上还是使用了枚举器

可变数组(NSMutableArray)

其实就是NSArray的可变子类;
可以参照NSMutablestring,因此方法的使用和NSMuatblestring也类似

集合

NSSet就像是NSArray的父类,是无序的,不可重复的,无索引的集合,但实际上两者之间不存在父类关系;

NSSet的功能和方法

方法还是看书上的
在这里插入图片描述

#import <Foundation/Foundation.h>
NSString* NSCollectionToString (id collection) {
    NSMutableString* result = [NSMutableString stringWithString:@"["];
    for (id object in collection) {
        [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 {
        NSSet* set1 = [NSSet setWithObjects:@"黄皮耗子",@"蒜头王八",@"音箱蟀侠",@"黄皮耗子", nil];
        NSLog(@"%ld",set1.count);
        NSLog(@"%@",NSCollectionToString(set1));
        NSSet* set2 = [NSSet setWithObjects:@"孙悟空",@"黄皮耗子",@"猪八戒", nil];
        NSLog(@"%@",NSCollectionToString(set2));
        set1 = [set1 setByAddingObject:@"炸弹猫"];
        NSLog(@"%@",NSCollectionToString(set1));
        NSSet* s = [set1 setByAddingObjectsFromSet:set2];
        NSLog(@"%@",NSCollectionToString(s));
        BOOL b = [set1 intersectsSet:set2];
        BOOL bo = [set2 isSubsetOfSet:set1];
        BOOL bb = [set1 containsObject:@"蒜头王八"];
        NSLog(@"%d %d %d",b,bo,bb);
        NSLog(@"%@ %@",[set1 anyObject],[set1 anyObject]);
        NSSet* w = [set1 objectsPassingTest:^BOOL(id  _Nonnull obj, BOOL * _Nonnull stop) {
            return (BOOL) ([obj length] > 3);
        }];
        NSLog(@"%@",NSCollectionToString(w));
    }
    return 0;
}

需要补充的点
anyobject方法返回的值不是随机的,如果在同一处重复调用该方法返回的值是一样的;
过滤的标志是passTest,其代码块的返回值是yes或no;

NSSet判断集合元素重复的标准

标准如下:
isEqual返回yes
hash的返回值相同;

每次判断都要调用hash方法判断返回值hashcode是否相等,因此常常要重写hash方法和isEqual方法;

#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;
@end

NS_ASSUME_NONNULL_END

#import "FKUser.h"

@implementation FKUser
@synthesize name;
@synthesize pass;
- (id)initWithName:(NSString *)name Pass:(NSString *)pass {
    if (self = [super init]) {
        self.name = name;
        self.pass = pass;
    }
    return self;
}
- (NSUInteger) hash {
    NSLog(@"hash");
    NSUInteger namehash = name == nil ? 0 : [name hash];
    NSUInteger passhash = pass == nil ? 0 : [pass hash];
    return namehash* 31 + passhash;
}
- (BOOL)isEqual:(id)object {
    if (object == self) {
        return YES;
    }
    if (object != nil &&[object isMemberOfClass:FKUser.class] ) {
        FKUser* target = object;
        if ([target.name isEqual:name] && [target.pass isEqual:pass]) {
            return YES;
        }
    }
    return  NO;
}
@end

#import <Foundation/Foundation.h>
#import "FKUser.h"
NSString* NSCollectionToString (id collection) {
    NSMutableString* result = [NSMutableString stringWithString:@"["];
    for (id object in collection) {
        [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 {
        NSSet* set1 = [NSSet setWithObjects:[[FKUser alloc]initWithName:@"sun" Pass:@"123"],[[FKUser alloc]initWithName:@"bai" Pass:@"345"],[[FKUser alloc]initWithName:@"sun" Pass:@"123"],[[FKUser alloc]initWithName:@"tang" Pass:@"178"],[[FKUser alloc]initWithName:@"niu" Pass:@"155"], nil];
        NSLog(@"%ld",[set1 count]);
        NSLog(@"%@",NSCollectionToString(set1));
    }
    return 0;
}

return namehash* 31 + passhash;
这样可以避免偶然性;
hash方法的重写有以下规则:
在这里插入图片描述
NSMutableSet代表可变的NSSet;区别不大,注意改变的自身就可以了

NSCountset的功能和用法

和NSSet的区别在于它会记录维护一个count记录元素进入集合的次数,包括重复元素;
方法还是看书,区别不大
在这里插入图片描述

NSOrdderSet和它的可变类,和NsSet的区别在于其有索引和顺序,方法的区别也在于这两点;

字典(NSDictionary和NSMutabledictionary)

NSDictionary是保存映射对的集合

NSDictionary的功能与用法

在这里插入图片描述
代码如下:

#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;
@end

NS_ASSUME_NONNULL_END

@implementation FKUser
@synthesize name;
@synthesize pass;
- (id)initWithName:(NSString *)name Pass:(NSString *)pass {
    if (self = [super init]) {
        self.name = name;
        self.pass = pass;
    }
    return self;
}
- (NSUInteger) hash {
    NSLog(@"hash");
    NSUInteger namehash = name == nil ? 0 : [name hash];
    NSUInteger passhash = pass == nil ? 0 : [pass hash];
    return namehash* 31 + passhash;
}
- (BOOL)isEqual:(id)object {
    if (object == self) {
        return YES;
    }
    if (object != nil &&[object isMemberOfClass:FKUser.class] ) {
        FKUser* target = object;
        if ([target.name isEqual:name] && [target.pass isEqual:pass]) {
            return YES;
        }
    }
    return  NO;
}
@end
#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface NSDictionary (print)
- (void) print;
@end

NS_ASSUME_NONNULL_END
#import "NSDictionary+print.h"

@implementation NSDictionary (print)
- (void) print {
    NSMutableString* str1 = [NSMutableString stringWithString:@"{"];
    for (id key in self) {
        [str1 appendString:[key description]];
        [str1 appendString:@"="];
        [str1 appendString:[self[key] description]];
        [str1 appendString:@","];
    }
    NSUInteger len = [str1 length];
    [str1 deleteCharactersInRange:NSMakeRange(len-1, 1)];
    [str1 appendString:@"}"];
}
@end

#import <Foundation/Foundation.h>
#import "FKUser.h"
#import "NSDictionary+print.h"
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys:[[FKUser alloc]initWithName:@"sun" Pass:@"123"], @"one", [[FKUser alloc]initWithName:@"bai" Pass:@"345"], @"two", [[FKUser alloc]initWithName:@"sun" Pass:@"123"], @"three", [[FKUser alloc]initWithName:@"tang" Pass:@"178"], @"four", [[FKUser alloc]initWithName:@"niu" Pass:@"155"], @"five", nil];
        [dict print];
        NSLog(@"%ld",[dict count]);
        NSLog(@"%@",[dict allKeys]);
        NSLog(@"%@",[dict allKeysForObject:[[FKUser alloc]initWithName:@"sun" Pass:@"123"]]);
        NSEnumerator* en = [dict objectEnumerator];
        NSString* value;
        while (value = [en nextObject]) {
            NSLog(@"%@",value);
        }
        [dict enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull key, id  _Nonnull obj, BOOL * _Nonnull stop) {
            NSLog(@"%@",key);
        }];
    }
    return 0;

要注意的是all开头的方法返回的是NSArray的数组;
其他与NSArray和NSSet的方法类似;
count返回的是映射对数;
枚举器枚举的对象是value,但快速枚举的对象是key;
可以通过key作为下标来使用value;

NSDictionary的排序,过滤可变字典的使用

其实都和NSArray和NSSet类似;
以下是一些区别:
sort是对value进行排序,然后返回排序后对应的key的NSArray数组;

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface NSDictionary (print)
- (void) print;
@end

NS_ASSUME_NONNULL_END

#import "NSDictionary+print.h"

@implementation NSDictionary (print)
- (void) print {
    NSMutableString* str1 = [NSMutableString stringWithString:@"{"];
    for (id key in self) {
        [str1 appendString:[key description]];
        [str1 appendString:@"="];
        [str1 appendString:[self[key] description]];
        [str1 appendString:@","];
    }
    NSUInteger len = [str1 length];
    [str1 deleteCharactersInRange:NSMakeRange(len-1, 1)];
    [str1 appendString:@"}"];
}
@end

#import <Foundation/Foundation.h>
#import "NSDictionary+print.h"
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:89],@"one",[NSNumber numberWithInt:69],@"two",[NSNumber numberWithInt:75],@"three",[NSNumber numberWithInt:109],@"four", nil];
        [dict print];
        NSSet* set1 = [dict keysOfEntriesPassingTest:^BOOL(id  _Nonnull key, id  _Nonnull obj, BOOL * _Nonnull stop) {
            return (BOOL)([obj intValue] > 80);
        }];
        NSLog(@"%@",set1);
    }
    return 0;
}

以上代码实现了一次过滤,只需注意过滤判断返回的是NSSet集合;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值