使用NSPointerArray,如何迭代不透明指针?

时间:2014-03-24 00:07:05

标签: objective-c foundation nsfastenumeration nspointerarray

我最近发现像NSMapTableNSPointerArray这样的类,它们像传统的集合一样工作,但也允许你存储弱引用或普通的旧C指针。不幸的是,您似乎无法使用for...in语法来迭代非NSObject指针。例如:

typedef struct Segment {
    CGPoint bottom, top;
} Segment;
...
NSPointerArray *segments = [[NSPointerArray alloc] 
                                 initWithOptions:NSPointerFunctionsOpaqueMemory];
...
Segment *s = malloc(sizeof(Segment));
[segments addPointer: s];
...
for (Segment *s in segments) {   // nope...

编译器不喜欢最后一行。错误:

  

选择器元素类型'段*' (又名' struct Segment *')不是有效对象

那么,我需要这样做吗?

for (int i=0, len=segments.count; i<len; i++) {
    Segment *seg = [segments pointerAtIndex:i];
    ...

那不是世界末日,但我只是想确定一下。

2 个答案:

答案 0 :(得分:4)

(这可能更符合理论上的兴趣。) NSPointerArray 符合NSFastEnumeration协议,它只是。{ for (id object in collection)语言构造,不能与任意指针一起使用 不是Objective-C指针。

但是你可以通过调用NSFastEnumeration从数组中获得一大堆指针 方法countByEnumeratingWithState:objects:count:直接。这有点棘手,因为 该方法无需填充提供的缓冲区(如下所述:How for in loop works internally - Objective C - Foundation)。

这是一个简单的例子:

__unsafe_unretained id objs[10];
NSUInteger count = [segments countByEnumeratingWithState:&state
                                                 objects:objs count:10];

// Now state.itemsPtr points to an array of pointers:
for (NSUInteger i = 0; i < count; i++) {
    Segment *s = (__bridge Segment *)state.itemsPtr[i];
    NSLog(@"%p", s);
}

因此,这无助于使代码更简单,您可能希望坚持使用 你的显式循环。

但是对于大型数组,它可能会提高性能,因为指针是&#34;取出的&#34; 分别从数组而不是每个指针分批。

答案 1 :(得分:1)

for(... in ...)语法在这种情况下不起作用,因为Segment是结构,而不是Objective C对象。你的第二个for循环应该可以工作。