我很长时间没有实现二进制文件,最近有要求这样做(演示一些代码),我开始使用:
@interface NSNode : NSObject
@property (strong, nonatomic) NSNode *leftChild;
@property (strong, nonatomic) NSNode *rightChild;
但是后来,似乎每当我需要对两个节点做一些事情时,我需要写两次 - 一次是针对左边的孩子,一次是针对正确的孩子,除非我做了需要做的事情。一个额外的方法,并仔细传递适当的参数 - 将有很多额外的方法来实现这一目标。
如果是通过使用NSMutableArray
完成的typedef enum {
NSNodeLeft = 0,
NSNodeRight
} NSNodeLeftOrRightSide;
@interface NSNode : NSObject
@property (strong, nonatomic) NSMutableArray *children;
然后我总是可以使用循环对两个节点做一些事情:
for (NSNode *node in self.children) {
// do something
}
或者,如果需要索引来判断它是左或右孩子:
[self.children enumerateObjectsUsingBlock:
^(NSNode *node, NSUInteger nodeIndex, BOOL *stop) {
// do something
}
];
并且nodeIndex
可用于确定它是左孩子还是右孩子。
而且,这个课程可以很容易地扩展到有N个孩子的树。这实际上是一种更好的做法吗?除了使用数组的非常小的性能外,是否有任何缺点? (我选择了NSMutableArray
代替NSArray
,因为如果我们需要制作这些N小孩,我们无需在整个地方将其更改为NSMutableArray
。
答案 0 :(得分:3)
当你需要对两个孩子做某事时,你总是可以使用一个阵列
for (Node *node in @[self.leftChild, self.rightChild]) {
// ...
}
如果你想让它变得更简单,你可以定义一个返回- (NSArray *)children
的方法@[self.leftChild, self.rightChild]
。但是将可变属性保留为不同的子元素是有用的,因为它明确地编码了这样一个事实,即您的节点只有2个子节点而不是无限数量的子节点。
答案 1 :(得分:2)
首先,您应该不使用名称NSNode
。 Apple保留NS
前缀供自己使用。
其次,只需给你的Node
类提供自己的枚举消息。
@interface Node : NSObject
- (void)enumerateChildrenUsingBlock:(void (^)(Node *child, NSUInteger childIndex, BOOL *stop))block;
// I prefer this shorter name style in my own classes:
- (void)forEachChild:(void (^)(Node *child, NSUInteger childIndex, BOOL *stop))block;
实施它是微不足道的:
@implementation Node
- (void)enumerateChildrenUsingBlock:(void (^)(Node *child, NSUInteger childIndex, BOOL *stop))block {
BOOL stop = NO;
block(self.leftChild, 0, &stop);
if (!stop) {
block(self.rightChild, 1, &stop);
}
}
如果你实现了NSFastEnumeration
协议,你也可以像这样写一个for / in循环:
for (Node *child in parentNode) {
// do something with child
}
您可以像这样实施NSFastEnumeration
:
@interface Node : NSObject <NSFastEnumeration>
...
@implementation Node
- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id *)stackbuf count:(NSUInteger)stackbufCount {
// The compiler initializes state->state to 0 at the start of the for...in loop.
// I use it to track which children have been returned.
// 0 = no children returned yet
// 1 = left children returned
// 2 = both children returned
state->itemsPtr = stackbuf;
state->mutationsPtr = (__bridge unsigned long *)self;
NSUInteger count = 0; // number of children I'm returning on this call
if (state->state < 1 && count < stackbufCount) {
stackbuf[count++] = self.leftChild;
++state->state;
}
if (state->state < 2 && count < stackbufCount) {
stackbuf[count++] = self.rightChild;
++state->state;
}
return count;
}
有关快速枚举的更多信息,请参阅此文章:http://www.mikeash.com/pyblog/friday-qa-2010-04-16-implementing-fast-enumeration.html