OC foudation框架(下)的学习

OCfoudation框架(下)

前面学习了有关OCfoudation框架的部分内容,我们现在对于后面的内容继续学习。


文章目录

  • OCfoudation框架(下)
    • 数组(NSArray和NSMutableArray)
      • 对集合元素整体调用方法
      • 排序
      • 使用枚举器遍历元素
      • 快速枚举(for in)
      • 可变数组
    • 集合(NSSet 与 NSMutableSet)
      • 功能与用法
      • 判断元素重复的标准
      • NSMutableSet的功能和用法
      • NSCountedSet的用法
      • 有序集合
    • 字典
      • 功能和用法
      • 对key排序
      • 对key进行过滤
      • 用自定义类作为key
      • NSmutableDictionary

数组(NSArray和NSMutableArray)

创建数组的常见方法介绍:

  • arrary:创建一个不包含任何元素的空NSArray
  • arrayWithContentsOfFile:/initWithContentsOfFile:读取文件内容来创建
  • arrayWithObject:创建仅包含指定元素的NSArray
  • arrayWithObjects:创建包含指定的N个元素的NSArray;

下面我们通过一段代码来运用这个数组的一些方法。

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSArray* array = [NSArray arrayWithObjects:@"iOS", @"Android", @"Java讲义", @"Html", @"structs", @"nanxun", nil];
        NSLog(@"first: %@",[array objectAtIndex:0]);
        NSLog(@"last:%@", [array lastObject]);
        NSArray* arr1 = [array objectsAtIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(2, 3)]];
        NSLog(@"%@",arr1);
        NSLog(@"Android:%ld", [array indexOfObject:@"Android"]);
        NSLog(@"Android in (2,5): %ld", [array indexOfObject:@"Android" inRange:NSMakeRange(2, 3)]);
        array = [array arrayByAddingObject:@"nannan"];
        array = [array arrayByAddingObjectsFromArray:[NSArray arrayWithObjects:@"krystal", @"zitai", nil]];
        for (int i = 0; i < array.count; i++) {
            NSLog(@"%@", [array objectAtIndex:i]);
        }
        NSArray* arr2 = [array subarrayWithRange:NSMakeRange(5, 3)];
        [arr2 writeToFile:@"/Users/nanxun/Documents/testoc/foudation study/foudation study/myFile.txt" atomically:YES];
    }
    return 0;
}

打印结果如下:

在这里插入图片描述

接下来分析一下相关内容,先看我们在(2, 5)位置寻找Android的结果,发现他是一个数字9223372036854775807,这个数值实际上是NSNotFound这个常量的值,就下来我们通过两种方式在后面添加元素,arrayByAddingObject添加单个元素,arrayWithObjects方法是将一个数组中的元素全部追加到原数组后面。

同时可以看到,我门用程序直接输出数组的话,可知道中文无法正常输出,这个会转化成/U75af格式输出。

我们下面分析在NSArray中能否判断指定元素位于NSArray集合中的索引,我们的标准是什么?这个标准就是我们的isEqual: 方法,比较是否相同,为了理解这个部分的内容,我们建立一个FKUser来帮助自己理解相关内容。

接口部分

@interface FKUser : NSObject
@property (nonatomic, copy) NSString* name;
@property (nonatomic, copy) NSString* pass;
- (id) initWithName:(NSString*) aName pass:(NSString*) aPass;
- (void) say:(NSString*) content;
@end

实现部分

@implementation FKUser
- (id) initWithName:(NSString *)aName pass:(NSString *)aPass {
    if (self = [super init]) {
        self.name = aName;
        self.pass = aPass;
    }
    return self;
}
- (void) say:(NSString *)content {
    NSLog(@"%@说:%@", self.name, content);
}
- (BOOL) isEqual:(id)object {
    if (self == object) {
        return YES;
    }
    if ([object class] == [FKUser class]) {
        FKUser* target = (FKUser*) object;
        return [self.name isEqualToString:target.name] && [self.pass isEqualToString: target.pass];
    }
    return NO;
}
- (NSString*) description {
    return [NSString stringWithFormat:@"FKUser[_name = %@, _pass = %@]", self.name, self.pass];
}
@end

主函数部分

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSArray* array = [NSArray arrayWithObjects:
                          [[FKUser alloc] initWithName:@"sun" pass:@"123"],
                          [[FKUser alloc] initWithName:@"bai" pass:@"345"],
                           [[FKUser alloc] initWithName:@"zhu" pass:@"654"],
                            [[FKUser alloc] initWithName:@"tang" pass:@"178"],
                             [[FKUser alloc] initWithName:@"niu" pass:@"155"], nil];
        FKUser* newUser = [[FKUser alloc] initWithName:@"zhu" pass:@"654"];
        NSUInteger pos = [array indexOfObject:newUser];
        NSLog(@"newUser的位置为%ld", pos);
    }
    return 0;
}

输出结果为下:在这里插入图片描述

这里我们发现了一个事情就是我们重新创建了一个对象,虽然该对象与集合中的任何对象都不相同,但是我们的程序还是可以返回该FKUser对象在该集合中的索引,这是因为他调用的是我们的isEqual方法

对集合元素整体调用方法

如果只是简单的调用集合元素的方法,主要有两种方法:

  • makeObjectPerformSelector:依次调用NSArray集合中每个元素的指定方法需要传入一个SEL参数
  • makeObjectsPerformSelcetor:withObject:一次调用集合中每个元素的指定方法,该方法第一个参数SEL用于指定调用那个方法,第二个参数用于调用集合元素方法时候传入参数;第三参数用来控制是否终止迭代,如果在处理某个元素后,将第三个元素复制为YES,该方法就终止迭代调用。

如果希望对集合中所有元素进行隐式遍历,并使用集合元素来执行某一段代码,可以使用以下三种方式

  • enumerateObjectUsingBlock: 遍历集合中的所有元素,并依次使用元素来执行指定的代码块
  • enumerateObjectsWithOptions:usingBolck: 和上面的差别就是可以传入一个号控制遍历的选项。
  • enumerateObjectAtIndexes:options:usingBlock: 这个它增加了一个遍历指定范围内的元素,并一次使用元素来执行指定的代码块。
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSArray* array = [NSArray arrayWithObjects:
                          [[FKUser alloc] initWithName:@"sun" pass:@"123"],
                          [[FKUser alloc] initWithName:@"bai" pass:@"345"],
                           [[FKUser alloc] initWithName:@"zhu" pass:@"654"],
                            [[FKUser alloc] initWithName:@"tang" pass:@"178"],
                             [[FKUser alloc] initWithName:@"niu" pass:@"155"], nil];
        [array makeObjectsPerformSelector:@selector(say:) withObject:@"下午好,NSArray真强大"];
        NSString* content = @"疯狂iOS讲义";
        [array enumerateObjectsAtIndexes: [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(2, 2)]options:NSEnumerationReverse usingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
            NSLog(@"正在处理第%ld个元素,%@",idx, obj);
            [obj say:content];
        }];
    }
    return 0;
}

打印结果如下:

在这里插入图片描述

这两段代码,主要调用了两个函数,一个是调用了**makeObjectsPerformSelector:**方法通过withObjects为say方法传入参数.

第二个则是应用了enumerateObjectsAtIndexes:options:usingBlock:方法并用这些元素来这些指定的代码块,传入的代码块参数就代表程序对每个集合元素迭代执行的代码体。(笔者这里对与Block不了解,还需要后续学习进行补充)。

排序

对数组的排序函数主要有三种:

  • sortedArrayUsingFunction:contes:该方法使用排序函数对集合元素进行一个排序,该排序函数必须返回NSOrderedDesceding,NSOrderedAscending,NSOrderedSame三个枚举常量。
  • sortedArrayUsingSelector:该方法使用集合元素自身的方法对集合元素进行排序,它的排序函数同样会返回上面给出的三个枚举值。
  • sortedArrayUsingComparator:该方法使用代码块对与集合元素进行排序

三种方法的返回值都是一个排好序的NSArray对象。

下面演示一下我们对于NSArray集合元素进行一个排序。

NSInteger inSort (id num1, id num2, void* context) {
    int v1 = [num1 intValue];
    int v2 = [num2 intValue];
    if (v1 < v2) {
        return NSOrderedAscending;
    } else if (v1 == v2) {
        return NSOrderedSame;
    } else {
        return NSOrderedDescending;
    }
}
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSArray* array1 = [NSArray arrayWithObjects:@"C++",@"Python",@"Perl",@"C",@"Objective-C",@"Ruby", nil];
        array1 = [array1 sortedArrayUsingSelector:@selector(compare:)];
        NSLog(@"%@", array1);
        NSArray* array2 = [NSArray arrayWithObjects:[NSNumber numberWithInt:20], [NSNumber numberWithInt:12], [NSNumber numberWithInt:-8],[NSNumber numberWithInt:50], [NSNumber numberWithInt:19],nil];
        array2 = [array2 sortedArrayUsingFunction:inSort context:nil];
        NSLog(@"%@", array2);
        NSArray* array3 = [array2 sortedArrayUsingComparator:^(id obj1, id obj2) {
            if ([obj1 intValue] > [obj2 intValue]) {
                return NSOrderedDescending;
            } else if ([obj1 intValue] < [obj2 intValue]) {
                return NSOrderedAscending;
            } else {
                return NSOrderedSame;
            }
        }];
        NSLog(@"%@", array3);
    }
    return 0;
}

打印结果如下:

在这里插入图片描述

在上述代码中间我们示范了三种对于NSArrary进行排序的三种方法,第一种是调用NSString自身的compaer:方法进行排序(compare的比较和成语言中的strcmp()函数相似)。

后面是两种不同的方法,一个是调用代码块,一个是调用函数的方法。

使用枚举器遍历元素

我们有两个方法获得枚举器

  • objectEnumerator:正序遍历
  • reverseObjectEnumerator:逆序遍历

枚举器的方法有以下两个

  • allObjects:获取枚举集合中所有的元素
  • reverseObjectEnumerator:获取被枚举集合中的下一个元素。
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSArray* array1 = [NSArray arrayWithObjects:@"C++",@"Python",@"Perl",@"C",@"Objective-C",@"Ruby", nil];
        NSEnumerator* en = [array1 objectEnumerator];
        id object;
        while (object = [en nextObject]) {
            NSLog(@"%@", object);
        }
        NSLog(@"");
        NSEnumerator* an = [array1 reverseObjectEnumerator];
        while (object = [an nextObject]) {
            NSLog(@"%@", object);
        }
        
    }
    return 0;
}

打印结果为:

在这里插入图片描述

一种是升序,另一种是降序。

快速枚举(for in)

快速枚举的语法格式如下:

for(type variableName in collection) {
  //variableName自动迭代访问每一个元素
}

tips:这里面如果用快速枚举来遍历NSDictionary对象的时候,它代表的是key值

下面给出一个示范

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSArray* array1 = [NSArray arrayWithObjects:@"C++",@"Python",@"Perl",@"C",@"Objective-C",@"Ruby", nil];
        for (id object in array1) {
            NSLog(@"%@", object);
        }
        
    }
    return 0;
}

打印结果如下

在这里插入图片描述

可变数组

NSArray代表元素不可变的集合,一旦创建成功,程序不能向集合调价新的元素,这时候我们就要运用到我们的NSMutableArray.

它给出了增加(add),删除(remove),替换(replace)元素的方法。

NSMutableArray还提供了sortUsingSelector:、sortUsingComparator:、sortUsingFunction: context:方法,它们与前面介绍的NSArray的排序的方法类似,区别是NSArray的排序的方法返回的是一个新的NSArray对象,而NSMutableArray返回的是排序后的原来的对象。

下面给出代码示范

NSString *NSCollectionToString(NSArray *array) { // 将集合中的所有元素合成一个字符串便于我们打印
    NSMutableString *result = [NSMutableString stringWithString:@"["];
    for (id obj in array) {
        [result appendString: [obj description]];
        [result appendString:@","];
    }
    NSUInteger len = [result length];
    [result deleteCharactersInRange:NSMakeRange(len - 1, 1)];//去掉最后一个字符
    [result appendString:@"]"];
    return result;
}
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSMutableArray* array1 = [NSMutableArray arrayWithObjects:@"C++",@"Python",@"Perl",@"C",@"Objective-C",@"Ruby", nil];
        [array1 addObject:@"Java"];
        NSLog(@"%@", NSCollectionToString(array1));
        [array1 addObjectsFromArray:[NSArray arrayWithObjects:@"Js", @"Ts", nil]];
        NSLog(@"%@", NSCollectionToString(array1));
        [array1 insertObject:@"Android" atIndex:2];
        NSLog(@"%@", NSCollectionToString(array1));
        [array1 insertObjects:[NSArray arrayWithObjects:@"web",@"server", nil] atIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(3, 2)]];
        NSLog(@"%@", NSCollectionToString(array1));
        [array1 removeLastObject];
        NSLog(@"%@", NSCollectionToString(array1));
        [array1 removeObjectAtIndex:5];
        NSLog(@"%@", NSCollectionToString(array1));
        [array1 replaceObjectAtIndex:2 withObject:@"疯狂iOS"];
        NSLog(@"%@", NSCollectionToString(array1));
    }
    return 0;
}

打印结果如下:

在这里插入图片描述

集合(NSSet 与 NSMutableSet)

NSSet集合不允许包含相同的元素(它没有明显的顺序),如果试图将两个相同的元素放在同一个NSSet集合中,则只会保留一个元素

功能与用法

实际上,NSArray与NSSet依然有大量的相似之处。

  • 都可以通过count方法获取集合元素数量
  • 可以用快速枚举遍历集合元素
  • 可以通过objectEnumerator方法获取NSEnumerator枚举器对集合元素遍历。
  • 提供了makeObjectsPerformSelector:方法对集合元素真题调用某个方法

接下来我们介绍一下NSSet的常用方法

  • setByAddingObject:向集合中添加一个新元素,返回添加元素后的新集合
  • setByAddingObjectsFromSet:使用NSSet集合向集合中添加多个新元素,返回新集合
  • setByAddingObjectsFromArray:使用NSArray集合向集合中添加多个新元素,返回新集合
  • allObjects:返回集合中所有元素组成的NSArray
  • anyObject:返回集合中的某个元素。(但是并不保证随机返回集合元素)。
  • containsObject:判断集合是否包含指定元素
  • Member:判断该集合是否包括与该参数相等的元素,如果包含就返回相等的元素,反之则返回nil。
  • objectsPassingTest:需要传入一个代码块对集合元素进行一个过滤,满足该代码块的集合元素会被保留下来并组成一个新的NSSet集合作为返回值
  • objectsWithOptions:passingTest:和前一个方法的功能基本相似,只是可以额外地传入一个NSEnumerationOptions作为迭代参数
  • isSubsetOfSet:判断是否为一个子集
  • intersectsSet:判断是否有交集
  • isEqualToset:判断集合是否相同

下面给出一段代码来理解相关内容

NSString *NSCollectionToString(id array) {
    NSMutableString *result = [NSMutableString stringWithString:@"["];
    for (id obj in array) {
        [result appendString: [obj description]];
        [result appendString:@","];
    }
    NSUInteger len = [result length];
    [result deleteCharactersInRange:NSMakeRange(len - 1, 1)];//去掉最后一个字符
    [result appendString:@"]"];
    return result;
}
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSSet* set1 = [NSSet setWithObjects:@"iOS", @"Andirod",@"web",@"server", nil];
        NSLog(@"set个数为%ld", [set1 count]);
        NSLog(@"%@", NSCollectionToString(set1));
        NSSet* set2 = [NSSet setWithObjects:@"krystal",@"xiyang",@"fenfneko",@"web", nil];
        NSLog(@"%@", NSCollectionToString(set2));
        set1 = [set1 setByAddingObject:@"shenyi"];
        NSSet* s1 = [set1 setByAddingObjectsFromSet:set2];
        NSLog(@"并集合%@", NSCollectionToString(s1));
        BOOL bo = [set2 isSubsetOfSet: set1];
        NSLog(@"set2是否是set1子集集%ld",bo);
        BOOL bb = [set1 containsObject:@"Andirod"];
        NSLog(@"是否包含Andirod:%ld", bb);
        NSLog(@"从set1中取出一个%@",[set1 anyObject]);
        NSSet* fileteredSet = [set1 objectsPassingTest:^(id obj, BOOL *stop) {
            return (BOOL)([obj length] > 3);
        }];
        NSLog(@"set1中元素长度大于8的集合元素有%@",NSCollectionToString(fileteredSet));
        
    }
    return 0;
}

下面是代码的结果:

在这里插入图片描述

这部分内容主要是一个演示相关代码的一个作用。

判断元素重复的标准

这里涉及到了一个Hash表的内容,我们每存入一个元素那么我们的NSSet会带调用该对象的一个Hash方法来计算一个Hash值,然后根据HashCode计算出元素在底层Hash表中的存储位置。如果出现了两个元素通过了isEqual方法但是它俩的值相同,那么我们这里的方式是通过链表将这两个元素连接起来。

这里我们就可以知道NSSet中判断两个元素是否相等的标准如下:

  • 两个对象通过isEqual的方法返回YES
  • 两个对象的hash方法的返回值也相等
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSSet* array = [NSSet setWithObjects:
                                  [[FKUser alloc] initWithName:@"sun" pass:@"123"],
                                  [[FKUser alloc] initWithName:@"bai" pass:@"345"],
                                   [[FKUser alloc] initWithName:@"zhu" pass:@"123"],
                                    [[FKUser alloc] initWithName:@"tang" pass:@"178"],
                                     [[FKUser alloc] initWithName:@"niu" pass:@"155"], nil];
        NSLog(@"元素个数为%ld", [array count]);
        NSLog(@"%@", NSCollectionToString(array));
    }
    return 0;
}

这是我们之前用过的FKUser类别,我们在这个类别中间定义了我们的isEqual:方法它只要name和oass相同就说明了我们的两个对象是相同的。但是打印结果却不符合我们的一个预期

在这里插入图片描述

发现出现了两个相同的元素,因此我们要重写一下Hash方法。

- (NSUInteger) hash {
    NSLog(@"===hash===");
    NSUInteger nameHash = _name == nil ? 0 : [_name hash];
    NSUInteger passHash = _pass == nil ? 0 : [_pass hash];
    return nameHash * 31 + passHash;
}

修改之后发现结果就恢复正常了。

在这里插入图片描述

这里我们发现了我们执行了5次Hash方法,这一步说明我们每次添加一个集合与安素,总是会先调用该元素的Hash方法,在重写这两种方法的时候,我们的目的主要是为了满足NSSet的性质,为了保证哦我们的NSSet保持一个较高的性能。

tips:Hash方法对于NSSet是非常重要的,下面给出重写Hash方法的基本原则。

  • 同一对象返回的Hash值应该是相同的
  • isEqual:方法比较返回YES的时候,这两个对象的Hash应返回相等的值·
  • 对象中所有被isEqual比较标准的实例变量都应该用来就算hashCode值。

一般情况我们的返回值都写成[f1 hash] * (质数) + [f2 hash]

NSMutableSet的功能和用法

和array相似,add(增加),remove(删除)。

主要要记住交,并,交,差集的函数

  • unionSet:计算并集
  • minusSet:计算差集
  • intersectSet:计算交集
  • setSet:用后一个元素替换已有集合中的所有元素
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSMutableSet* set1 = [NSMutableSet setWithCapacity:10];
        [set1 addObject:@"Java"];
        NSLog(@"add a one %@",NSCollectionToString(set1));
        [set1 addObjectsFromArray:[NSArray arrayWithObjects:@"krystal",@"xiyang",@"zzr", nil]];
        NSLog(@"add many %@", NSCollectionToString(set1));
        [set1 removeObject:@"xiyang"];
        NSLog(@"remove one %@",NSCollectionToString(set1));
        NSMutableSet* set2 = [NSSet setWithObjects:@"fenfenko",@"shenyi", nil];
        //[set1 unionSet: set2];
        //[set1 minusSet: set2];
        //[set1 intersectSet:set2];
        [set1 setSet:set2];
        NSLog(@"%@", NSCollectionToString(set1));
    }
    return 0;
}

打印结果如下:

在这里插入图片描述

NSCountedSet的用法

NSCountedSet主要是有一个特色就是它会为每一个元素增加一个该元素出现的个数,我们可以不可以添加元素,但是如果我们添加的元素重复了,但是会将该元素的添加次数加1.删除元素的时候也是将这个元素添加次数减1,知道它为0的时候,这个元素才会真正的从NSCountedSet中删除。

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSCountedSet* set1 = [NSCountedSet setWithObjects:@"iOS讲义",@"Android",@"Java", nil];
        [set1 addObject:@"Java"];
        [set1 addObject:@"Java"];
        NSLog(@"%@", NSCollectionToString(set1));
        NSLog(@"Java的添加次数为%ld", [set1 countForObject:@"Java"]);
        [set1 removeObject:@"Java"];
        NSLog(@"%@", NSCollectionToString(set1));
        NSLog(@"Java的添加次数为%ld", [set1 countForObject:@"Java"]);
        [set1 removeObject:@"Java"];
        [set1 removeObject:@"Java"];
        NSLog(@"%@", NSCollectionToString(set1));
        NSLog(@"Java的添加次数为%ld", [set1 countForObject:@"Java"]);
    }
    return 0;
}

打印结果为:

在这里插入图片描述

这里就很好的体现了我们的NSCountedSet的特色。

有序集合

NSOrderedSet最主要的点在于可以保持与安素的添加顺序,而且每一个元素都有缩影,可以根据缩影来操作元素。

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSOrderedSet* set = [NSOrderedSet orderedSetWithObjects:[NSNumber numberWithInt:40],[NSNumber numberWithInt:12],[NSNumber numberWithInt:-9],[NSNumber numberWithInt:20], nil];
        NSLog(@"first :%@", [set firstObject]);
        NSLog(@"last:%@", [set lastObject]);
        NSLog(@"索引为2的元素:%@", [set objectAtIndex:2]);
        NSIndexSet* indexSet = [set indexesOfObjectsPassingTest:^(id obj, NSUInteger idx, BOOL* stop) {
            return (BOOL)([obj intValue] > 10); // 返回大于10的值
        }];
        NSLog(@"%@", indexSet);
    }
    return 0;
}

请添加图片描述

字典

这里的字典和C++中的map大致相同,它拥有一个键值对,所有key放在一个Set集合中,但是如果我们采用一个allKeys方法来返回却是一个NSArray。

功能和用法

初始化方法:一般以dictionary开头

在这里插入图片描述

访问方式:

请添加图片描述

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

这段代码演示了两种经典的语法,通过key获取value值 self[key]

下面给出一段代码来演示相关内容。

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys:[[FKUser alloc] initWithName:@"krystal" pass:@"24"], @"one", [[FKUser alloc] initWithName:@"xiyang" pass:@"33"], @"two",[[FKUser alloc] initWithName:@"flandre" pass:@"111"], @"three", [[FKUser alloc] initWithName:@"fenfenko" pass:@"2222"], @"four",[[FKUser alloc] initWithName:@"krystal" pass:@"24"], @"five", nil];
        [dict print];
        NSLog(@"有多少个key-value对:%ld", [dict count]);
        NSLog(@"dict的所有key为%@", [dict allKeys]);
        NSLog(@"krystal对应的所有key为%@", [dict allKeysForObject:[[FKUser alloc] initWithName:@"krystal" pass:@"24"]]);
        NSEnumerator* en = [dict objectEnumerator];
        NSObject* value;
        while (value = [en nextObject]) {
            NSLog(@"%@", value);
        }
        [dict enumerateKeysAndObjectsUsingBlock:^(id key, id value, BOOL* stop) {
            NSLog(@"key的值为:%@",key);
            [value say:@"101牛逼"];
        }];
        
    }
    return 0;
}

请添加图片描述

请添加图片描述

这里就演示了我们的dictionary的相关的代码演示。

对key排序

他和对于数组的排序一样,都是类似的,它的返回值同样是那三个关键字:NSOrderedAscendingNSOrderedDescendingNSOrderedSame

接下来示范一下排序。

NSString *NSCollectionToString(id array) {
    NSMutableString *result = [NSMutableString stringWithString:@"["];
    for (id obj in array) {
        [result appendString: [obj description]];
        [result appendString:@","];
    }
    NSUInteger len = [result length];
    [result deleteCharactersInRange:NSMakeRange(len - 1, 1)];//去掉最后一个字符
    [result appendString:@"]"];
    return result;
}
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys:@"iOS",@"one",@"Android",@"two",@"Java",@"three",@"Objective-c",@"four", nil];
        [dict print];
        NSArray* keyArr1 = [dict keysSortedByValueUsingSelector:@selector(compare:)];
        NSLog(@"%@", keyArr1);
        NSArray* keyArr2 = [dict keysSortedByValueUsingComparator:^(id value1, id value2) {
            if ([value1 length] > [value2 length]) {
                return NSOrderedDescending;
            } else if ([value1 length] == [value2 length]) {
                return NSOrderedSame;
            } else {
                return NSOrderedAscending;
            }
        }];
        NSLog(@"%@", keyArr2);
        
    }
    return 0;
}

打印结果如下

请添加图片描述

对key进行过滤

  • keysOfEntriesPassingTest:使用代码块迭代处理key-value对,只有符合代码块条件的会留下来。一共接收三个参数,第一个是正在迭代处理的key,第二个参数代表正在迭代处理的value,第三个参数代表是是否需要继续迭代,如果第三个参数设置成NO,这个方法就会立即停止迭代。
  • keysOfEntriesWithOptions:passingTest:该方法的功能和前一个方法的功能基本相同,可以额外传入一个附加的NSEnumerationOptions的选项参数。
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:89], @"Objective-C",[NSNumber numberWithInt:69], @"Ruby",[NSNumber numberWithInt:75], @"Python",[NSNumber numberWithInt:109], @"Prel", nil];
        [dict print];
        NSSet* keySet = [dict keysOfEntriesPassingTest:^(id key, id value, BOOL* stop) {
            return (BOOL)([value intValue] > 80);
        }];
        NSLog(@"%@", keySet);
    }
    return 0;
}

打印结果如下:

请添加图片描述

用自定义类作为key

我们可以用自己定义的类来作为key,但是要满足两个要求:

  • 正确重写isEqual:方法和hash方法
  • 自定义类实现了copyWithZone:方法,最好可以返回对象的不可变副
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        FKUser* u1 = [[FKUser alloc] initWithName:@"krystal" pass:@"24"];
        NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys:
                              @"one", [[FKUser alloc] initWithName:@"xiyang" pass:@"23"],
                              @"two", [[FKUser alloc] initWithName:@"flandre" pass:@"22"],
                              @"three", [[FKUser alloc] initWithName:@"xiyang" pass:@"23"],
                              @"four", [[FKUser alloc] initWithName:@"fenfenko" pass:@"19"],
                              @"five", [[FKUser alloc] initWithName:@"niu" pass:@"155"],
                              @"six", u1, nil];
        u1.pass = nil;
        [dict print];
    }
    return 0;
}

打印结果如下:

请添加图片描述

这里我们可以看到它会让重复的key出现一次。

NSmutableDictionary

它其实也主要是提供了可以增加key-value对,和删除key-value对的一系列方法

请添加图片描述

代码演示

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSMutableDictionary* dict = [NSMutableDictionary dictionaryWithObjectsAndKeys:@"iOS", @"99", nil];
        dict[@"99"] = @"iOSS";
        [dict print];
        dict[@"Android"] = @"ddd";
        [dict print];
        NSDictionary* dict2 = [NSDictionary dictionaryWithObjectsAndKeys:@"Java", @"sss", @"python", @"struct", nil];
        [dict addEntriesFromDictionary:dict2];
        [dict print];
        [dict removeObjectForKey:@"sss"];
        [dict print];
    }
    return 0;
}

打印结果如下:

请添加图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/612042.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

SwinIR: Image Restoration Using Swin Transformer

ICCV2021 workshophttps://github.com/JingyunLiang/SwinIR 问题引入 将swim transformer使用到图像恢复任务当中&#xff0c;因为卷积存在不能建模长距离依赖以及使用相同的卷积核来恢复不同的图像区域&#xff1b;并不是首个将transformer引入图像恢复中的方法&#xff0c;…

简单的Python HTML 输出

1、问题背景 一名初学者在尝试将 Python 脚本输出到网页上时遇到了一些问题。他当前使用 Python 和 HTML 进行开发&#xff0c;并且遇到了以下问题&#xff1a; 担心自己的代码过于复杂&#xff0c;尤其是 WebOutput() 函数。希望通过 JavaScript 使用 HTML 模板文件更新数据。…

Java多线程与并发编程

1.多线程基础 1.1 线程相关概念 程序(program)&#xff1a;是为完成特定任务、用某种语言编写的一组指令的集合。简单的说:就是我们写的代码 进程: 1. 进程是指运行中的程序&#xff0c;比如我们使用QQ&#xff0c;就启动了一个进程&#xff0c;操作系统就会为该进程…

常见扩频系统的基础概念和模型

扩频系统是一种通信技术&#xff0c;它通过将信号的频谱扩展到一定程度来实现传输&#xff0c;这种系统的设计和实现涉及到多种不同的方法和技术。 扩频系统的主要特点和好处包括&#xff1a; 抗干扰能力强&#xff1a;由于信号被扩展到较宽的频带上&#xff0c;单位带宽内的功…

数据收集-分化轨迹推断

数据收集-分化轨迹推断 1参考内容 2参考内容 3参考内容 4参考内容 5参考内容 6&#xff1a;methods and datasets review参考内容 1 参考 Ranek, J.S., Stanley, N. & Purvis, J.E. Integrating temporal single-cell gene expression modalities for trajectory inferen…

【p7】正规式转正规文法

需要注意的是&#xff0c;有时候需要自己构造一个非终结符&#xff0c;非终结符推导到空&#xff0c;然后套用上面的公式即可

十大排序算法(java实现)

注&#xff1a;本篇仅用来自己学习&#xff0c;大量内容来自菜鸟教程&#xff08;地址&#xff1a;1.0 十大经典排序算法 | 菜鸟教程&#xff09; 排序算法可以分为内部排序和外部排序&#xff0c;内部排序是数据记录在内存中进行排序&#xff0c;而外部排序是因排序的数据很大…

SpringCloud面试题

SpringCloud常见组件有哪些 注册中心组件&#xff1a;Eureka、Nacos 负载均衡组件&#xff1a;Ribbon 远程调用组件&#xff1a;OpenFeign 网关组件&#xff1a;Zuul、Gateway 服务保护组件&#xff1a;Hystrix、Sentinel 服务配置管理组件&#xff1a;SpringCloudConfig、Nac…

OpenCompass大模型评估

作业链接&#xff1a; Tutorial/opencompass/homework.md at camp2 InternLM/Tutorial GitHub 项目链接&#xff1a; GitHub - open-compass/opencompass: OpenCompass is an LLM evaluation platform, supporting a wide range of models (Llama3, Mistral, InternLM2,GPT-…

Docker快速搭建NAS服务——FileBrowser

Docker快速搭建NAS服务——FileBrowser 文章目录 前言FileBrowser的搭建docker-compose文件编写运行及访问 总结 前言 本文主要讲解如何使用docker在本地快速搭建NAS服务&#xff0c;这里主要写如下两种&#xff1a; FileBrowser1&#xff1a;是一个开源的Web文件管理器&…

【吊打面试官系列】Java高并发篇 - 为什么 wait(), notify()和 notifyAll ()必须在同步方法或者同步块中被调用?

大家好&#xff0c;我是锋哥。今天分享关于 【为什么 wait(), notify()和 notifyAll ()必须在同步方法或者同步块中被调用&#xff1f;】面试题&#xff0c;希望对大家有帮助&#xff1b; 为什么 wait(), notify()和 notifyAll ()必须在同步方法或者同步块中被调用&#xff1f;…

这3种深拷贝实现,你都知道吗?

目录&#xff1a; 1、JSON.parse 2、structuredClone 3、cloneDeep

【竞技宝jjb.lol】MSI:换线战术或将成为BLG命门

北京时间2024年5月10日,英雄联盟2024MSI季中赛继续进行,昨日迎来胜败分组赛首轮BLG对阵PSG。本以为这场比赛没有任何悬念,BLG将会非常轻松地击败PSG,没想到最终PSG两度扳平比分,BLG决胜局抗住压力才艰难取胜。虽然赢下了比赛,但BLG低迷的状态还是在比赛结束后遭到网友们的热议。…

超全MySQL锁机制介绍

前言 MySQL作为关系型数据库管理系统中的佼佼者&#xff0c;为了保证数据的一致性和完整性&#xff0c;在并发控制方面采用了锁机制。锁机制是数据库管理系统用于控制对共享资源的访问&#xff0c;避免多个事务同时修改同一数据造成的数据不一致问题。了解MySQL的锁机制对于数…

【组合博弈】介绍

本文为学习笔记&#xff0c;详细内容参考"Lessons in Play,Michael H. Albert Richard J. Nowakowski David Wolfe" 文章目录 组合博弈介绍(Combinatorial Games)DOMINEERING游戏组合游戏选手介绍Options博弈树&#xff08;game tree&#xff09; 组合博弈介绍(Combi…

*****水上飞机:继承,虚函数,虚继承

一题目 请设计以下航行器、飞机、船、水上飞机等 4 个类。 CRAFT 为航行器类&#xff0c;是公共基类&#xff0c;提供航行器的基本特性。包括&#xff1a; 一个保护数据成员&#xff1a;speed(速度)。 三个公有成员函数&#xff1a;构造函数(初始化速度)、析构函数和 Show 函数…

ASP.NET学生成绩管理系统

摘要 本系统依据开发要求主要应用于教育系统&#xff0c;完成对日常的教育工作中学生成绩档案的数字化管理。开发本系统可使学院教职员工减轻工作压力&#xff0c;比较系统地对教务、教学上的各项服务和信息进行管理&#xff0c;同时&#xff0c;可以减少劳动力的使用&#xf…

操作系统实战(三)(linux+C语言实现)

实验目的 加深对进程调度概念的理解&#xff0c;体验进程调度机制的功能&#xff0c;了解Linux系统中进程调度策略的使用方法。 练习进程调度算法的编程和调试技术。 实验说明 1.在linux系统中调度策略分为3种 SCHED_OTHER&#xff1a;默认的分时调度策略&#xff0c;值为0…

通俗的理解网关的概念的用途(四):什么是网关设备?(网络层面)

任何一台Windows XP操作系统之后的个人电脑、Linux操作系统电脑都可以简单的设置&#xff0c;就可以成为一台具备“网关”性质的设备&#xff0c;因为它们都直接内置了其中的实现程序。MacOS有没有就不知道&#xff0c;因为没用过。 简单的理解&#xff0c;就是运行了具备第二…

使用nmcli命令在Linux系统上配置各种网络(有线、无线、vlan、vxlan、路由、网桥等)

前言&#xff1a;原文在我的博客网站中&#xff0c;持续更新数通、系统方面的知识&#xff0c;欢迎来访&#xff01; 使用nmcli命令在Linux系统上配置各种网络&#xff08;有线、无线、vlan、vxlan、路由、网桥等&#xff09;https://myweb.myskillstree.cn/123.html 你是否会…