概要
最近wantedlyでは、新人研修でjavaのデザインパターンを勉強してます。
ただ使っている言語は、objective-Cだったり、rubyだったりするので、自分の勉強も含めて、それぞれのパターンをそれぞれのどう実装していくか整理しながら進めてます。
iteratorパターン
forで数を数える場合、最後の数を間違えたりしてバグを生み出すことがあります。
またenumratorを利用することで、数を数えることとコレクションの実装を分けて考えることができます。
objective-Cでiteratorを利用する方法
NSFastEnumeration protocolを利用します。NSArrayやNSSetやNSDictionaryは、このprotocolを含んでます。
enumratorの使い分け
-
for in
で利用するのが基本です
for (id object in array) {
NSLog(@"%@", object);
}
-
while
で書く場合
id object = nil;
NSEnumerator *enumerator = ...;
while ((object = [enumerator nextObject])) {
NSLog(@"%@", object);
}
- NSArrayやNSSetやNSDictionaryやNSIndexSetではblockでenumerateを使うことができます。
[array enumerateObjectsUsingBlock:^(id object, NSUInteger idx, BOOL *stop) {
NSLog(@"%@", object);
}];
NSFastEnumrationのプロトコルの使い方
- NSFastEnumerationのプロトコルは、countByEnumeratingWithStateというmethodが必要になります
BookShelf.h
#import <Foundation/Foundation.h>
#define ARRAY_SIZE 32
@interface BookShelf : NSObject <NSFastEnumeration>
{
__unsafe_unretained id _objects[ARRAY_SIZE];
}
@end
BookShelf.m
#import "BookShelf.h"
@implementation BookShelf
- (id)init
{
self = [super init];
if (!self) {
return nil;
}
for (int i = 0; i < ARRAY_SIZE; i++) {
_objects[i] = [NSNumber numberWithInt:i];
}
return self;
}
- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id __unsafe_unretained [])buffer count:(NSUInteger)len
{
if (state->state >= ARRAY_SIZE) {
return 0;
}
state->itemsPtr = _objects;
state->state = ARRAY_SIZE;
state->mutationsPtr = &state->extra[0];
return ARRAY_SIZE;
}
@end
main.m
#import <Foundation/Foundation.h>
#import "BookShelf.h"
int main(int argc, const char * argv[])
{
@autoreleasepool {
BookShelf *bookShelf = [BookShelf new];
for (id object in bookShelf) {
NSLog(@"%@", object);
}
}
return 0;
}
参考
- ここを読むとより詳しいです http://nshipster.com/enumerators/
- Fast Enumerationについて http://news.mynavi.jp/column/objc/105/
- mutationPtrの指定方法 http://stackoverflow.com/questions/7815326/automatic-reference-counting-error-with-fast-enumeration
- 今回のソースのサンプル https://github.com/reikubonaga/objective-c-iterator