字符串的类型主要有两种,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,此时会自动创建一个文件;
以下是一些方法的使用
#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一般包括两种创建对象的方法,其中类方法以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对象,然后对该对象调用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的功能与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方法实现对已有对象的复制,返回原始对象的副本;
两种方法都是返回原始对象的副本,只是一个返回不可变的副本,一个返回可变的副本;
改变副本不会对原始对象产生影响;
#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;
}
上面代码中的注释就是两者间的区别所在;
当使用自定义的类进行复制时,不能直接调用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类的复制;这时会创建一个新的对象和地址,就不会出现副本改变造成的原始对象改变;
在定义属性时,我们常常会使用copy指示符;copy指示符实际上是在setter方法中付给成员变量的值是通过copy方法复制的不可变副本,即该属性一定是不可变的,可以看书上的例子,代码忘了写了
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;
}
主要可以归类于两种方法,一种使每一个元素调用指定的方法,另一种对每一个元素使用代码块进行操作;
注意一下代码块的格式和参数即可;
还要注意代码块中控制正序和倒序的参数即可
这两种方法也叫迭代方法;
排序方法都是以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方法返回遍历元素;
上面还提到了快速枚举,这是更为常用和简洁的枚举方法,但本质上还是使用了枚举器
其实就是NSArray的可变子类;
可以参照NSMutablestring,因此方法的使用和NSMuatblestring也类似
NSSet就像是NSArray的父类,是无序的,不可重复的,无索引的集合,但实际上两者之间不存在父类关系;
#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;
标准如下:
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;区别不大,注意改变的自身就可以了
和NSSet的区别在于它会记录维护一个count记录元素进入集合的次数,包括重复元素;
方法还是看书,区别不大
NSOrdderSet和它的可变类,和NsSet的区别在于其有索引和顺序,方法的区别也在于这两点;
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;
其实都和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集合;