在前一篇 Xcode 4.4/4.5 新特性 / LLVM 4.0 新语法 提到了 Xcode 4.4 之后对数组和字典的操作可以用下面的方式:
id value = array[i];
array[i] = newObj;
id value = dictionary[@"key"];
dictionary[@"key"] = newObj;
上面几行语句实际调用的方法分别对应如下:
NSArray : - (id)objectAtIndexedSubscript: (NSUInteger)index;
NSMutableArray : - (void)setObject: (id)obj atIndexedSubscript: (NSUInteger)index;
NSDictionary : - (id)objectForKeyedSubscript: (id <NSCopying>)key;
NSMutableDictionary : - (void)setObject: (id)anObject forKeyedSubscript: (id <NSCopying>)aKey;
所以,如果你希望自己定义的类可以支持 obj[i] 和 obj[@"key"] 的方式来读取和设置值的话,就可以实现上面相应的方法,只是要处理好你自己参数和结果类型。现在就来看看下面自定义类 TestClass 的实现和执行效果:
TestClass.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
// // TestClass.h // NewXcodeTest // // Created by Unmi on 1/22/13. // Copyright (c) 2013 Unmi. All rights reserved. // #import <Foundation/Foundation.h> @interface TestClass : NSObject - (id) objectAtIndexedSubscript: (NSUInteger)index; - (void) setObject: (id)obj atIndexedSubscript: (NSUInteger)index; - (id) objectForKeyedSubscript: (id <NSCopying>)key; - (void) setObject: (id)anObject forKeyedSubscript: (id <NSCopying>)aKey; @end |
必须在头文件中声明需要用到的读写方法,否则 test[i] 这样用时无法通过编译。
TestClass.m
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
// // TestClass.m // NewXcodeTest // // Created by Unmi on 1/22/13. // Copyright (c) 2013 Unmi. All rights reserved. // #import "TestClass.h" @implementation TestClass - (id) objectAtIndexedSubscript: (NSUInteger)index { NSLog(@"get value by index: %d", index); return @"Unmi"; } - (void) setObject: (id)obj atIndexedSubscript: (NSUInteger)index{ NSLog(@"set value %@, atIndex: %d", obj, index); } - (id) objectForKeyedSubscript: (id <NSCopying>)key { NSLog(@"get value by key: %@", key); return @"http://unmi.cc"; } - (void) setObject: (id)anObject forKeyedSubscript: (id <NSCopying>)aKey { NSLog(@"set value %@ for key: %@", anObject, aKey); } @end |
使用 TestClass 的代码:
1 2 3 4 5 |
TestClass* test = [[TestClass alloc] init]; id value = test[100]; test[1] = @200; value = test[@"Name"]; test[@"Blog"] = @"http://unmi.cc"; |
上面的代码执行效果如下,控制台输出:
2013-01-26 14:30:00.342 NewXcodeTest[955:c07] get value by index: 100
2013-01-26 14:30:00.344 NewXcodeTest[955:c07] set value 200, atIndex: 1
2013-01-26 14:30:00.346 NewXcodeTest[955:c07] get value by key: Name
2013-01-26 14:30:00.348 NewXcodeTest[955:c07] set value http://unmi.cc for key: Blog
对应一下,果真如此。
实际应用中,你可以在 TestClass 中声明些实例变量,比如数组,字典类型的变量,让以上的四个 Subscripting Methods 下标方法去访问这些实例变量中的值,这样从代码和语义上省去了些麻烦。比如 TestClass 中声明了一个字典实例变量 options 和数组变量 items,我们就无需写成:
test.options[@"name"],而可简单的写成 test[@"name"],test.items[i] 变成 test[i], 就是这么回事。
参考:1. Objective-C的新特性
2. WWDC2012:Objective-C的新特性