简体   繁体   English

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

[英]With NSPointerArray, how to iterate over opaque pointers?

I recently discovering these classes like NSMapTable and NSPointerArray , which work like the traditional collections, but also let you store weak references or plain old C pointers. 我最近发现像NSMapTableNSPointerArray这样的类,它们像传统的集合一样工作,但也允许你存储弱引用或普通的旧C指针。 Unfortunately it looks like you can't use the for...in syntax to iterate over non- NSObject pointers. 不幸的是,看起来你不能使用for...in语法迭代非NSObject指针。 For example: 例如:

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...

The compiler does not like that last line. 编译器不喜欢最后一行。 The error: 错误:

Selector element type 'Segment *' (aka 'struct Segment *') is not a valid object 选择器元素类型'Segment *'(又名'struct Segment *')不是有效对象

So, do I need to do this? 那么,我需要这样做吗?

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

That's not the end of the world, but I just want to make sure. 这不是世界末日,但我只想确定。

(This might be more of theoretical interest.) NSPointerArray does conform to the NSFastEnumeration protocol, it is only the for (id object in collection) language construct that cannot be used with arbitrary pointers which are not Objective-C pointers. (这可能更符合理论上的兴趣。) NSPointerArray 确实符合NSFastEnumeration协议,它只是for (id object in collection)语言构造,不能与不是Objective-C指针的任意指针一起使用。

But you can get a whole bunch of pointers from the array by calling the NSFastEnumeration method countByEnumeratingWithState:objects:count: directly. 但是你可以通过调用NSFastEnumeration方法countByEnumeratingWithState:objects:count: NSFastEnumeration从数组中获取一大堆指针。 This is a bit tricky because that method need not fill the supplied buffer (as explained here: How for in loop works internally - Objective C - Foundation ). 这有点棘手,因为该方法不需要填充提供的缓冲区(如下所述: in循环如何在内部工作 - Objective C - Foundation )。

Here is a simple example how this would work: 这是一个简单的例子:

__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);
}

So this does not help to make the code simpler and you probably want to stick with your explicit loop. 因此,这无助于使代码更简单,您可能希望坚持使用显式循环。

But for large arrays it might improve the performance because the pointers are "fetched" in batches from the array instead of each pointer separately. 但是对于大型数组,它可能会提高性能,因为指针是从数组中分批“取出”而不是分别指向每个指针。

the for (... in ...) syntax won't work in this case because Segment is a struct, not an Objective C object. for(... in ...)语法在这种情况下不起作用,因为Segment是结构,而不是Objective C对象。 Your second for loop should work. 你的第二个循环应该工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM