NSObject的hash方法
说明
本示例仅仅演示一个对象什么时候执行hash方法。
细节
1. 必要的Model类,重载了hash方法用以反映Hash方法是否被调用了
2. 测试
// // ViewController.m // Hash // // Created by YouXianMing on 16/4/15. // Copyright © 2016年 YouXianMing. All rights reserved. // #import "ViewController.h" #import "Model.h" @interface ViewController () @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; Model *model = [Model new]; [model hash]; model = nil; } @end
3. 测试 isEqual: 方法执行的时候是否会执行 hash 方法,打印情况里面是没有的
// // ViewController.m // Hash // // Created by YouXianMing on 16/4/15. // Copyright © 2016年 YouXianMing. All rights reserved. // #import "ViewController.h" #import "Model.h" @interface ViewController () @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; Model *modelA = [Model new]; Model *modelB = [Model new]; if ([modelA isEqual:modelB]) { NSLog(@"YES"); } else { NSLog(@"NO"); } } @end
4. 用 NSMutableSet 添加对象,这时候会执行hash方法,至于为何会执行2回 _(:з」∠)_ ?
// // ViewController.m // Hash // // Created by YouXianMing on 16/4/15. // Copyright © 2016年 YouXianMing. All rights reserved. // #import "ViewController.h" #import "Model.h" @interface ViewController () @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; Model *model = [Model new]; NSMutableSet *set = [NSMutableSet set]; [set addObject:model]; } @end
5. 用 NSMutableArray 添加对象测试一下,发现不会执行 hash 方法
// // ViewController.m // Hash // // Created by YouXianMing on 16/4/15. // Copyright © 2016年 YouXianMing. All rights reserved. // #import "ViewController.h" #import "Model.h" @interface ViewController () @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; Model *model = [Model new]; NSMutableArray *array = [NSMutableArray array]; [array addObject:model]; } @end
6. 用作 NSMutableDictionary 中的 object 时,hash 方法不会执行
// // ViewController.m // Hash // // Created by YouXianMing on 16/4/15. // Copyright © 2016年 YouXianMing. All rights reserved. // #import "ViewController.h" #import "Model.h" @interface ViewController () @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; Model *model = [Model new]; NSMutableDictionary *dictionary = [NSMutableDictionary dictionary]; [dictionary setObject:model forKey:@"A"]; [dictionary objectForKey:@"A"]; } @end
7. 用作 NSMutableDictionary 中的 key 时,hash 方法执行了,不过崩溃了,因为 Model 类没有实现 NSCopying 协议
// // ViewController.m // Hash // // Created by YouXianMing on 16/4/15. // Copyright © 2016年 YouXianMing. All rights reserved. // #import "ViewController.h" #import "Model.h" @interface ViewController () @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; Model *model = [Model new]; NSMutableDictionary *dictionary = [NSMutableDictionary dictionary]; [dictionary setObject:@"A" forKey:model]; } @end
8. NSSet 在初始化的时候添加了 model 并不会让 model 执行 hash 方法
// // ViewController.m // Hash // // Created by YouXianMing on 16/4/15. // Copyright © 2016年 YouXianMing. All rights reserved. // #import "ViewController.h" #import "Model.h" @interface ViewController () @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; Model *model = [Model new]; NSSet *set = [NSSet setWithObjects:model, nil]; if ([[set anyObject] isEqual:model]) { NSLog(@"A"); } set = nil; } @end
9. 在创建不可变数组时,model 作为 key 会执行 hash 方法,但同样会崩溃,因为 Model 类没有实现 NSCopying 协议
// // ViewController.m // Hash // // Created by YouXianMing on 16/4/15. // Copyright © 2016年 YouXianMing. All rights reserved. // #import "ViewController.h" #import "Model.h" @interface ViewController () @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; Model *model = [Model new]; NSDictionary *dictionary = @{model : @"A"}; dictionary = nil; } @end
总结
一个对象在用作key值时,其 hash 方法会被调用,用以生成一个唯一标识符,NSDictionary 需要根据唯一 key 值(根据 hash 算法生成的值)查找对象, NSSet 需要根据 hash 值来确保过滤掉重复的对象。