С NSPointerArray, как перебирать непрозрачные указатели?
Я недавно обнаружил эти классы, как NSMapTable
а также NSPointerArray
, которые работают как традиционные коллекции, но также позволяют хранить слабые ссылки или простые старые указатели Си. К сожалению, похоже, что вы не можете использовать 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...
Компилятору не нравится эта последняя строка. Ошибка:
Тип элемента селектора 'Segment *' (также известный как struct Segment * ') не является допустимым объектом
Итак, мне нужно сделать это?
for (int i=0, len=segments.count; i<len; i++) {
Segment *seg = [segments pointerAtIndex:i];
...
Это не конец света, но я просто хочу убедиться.
2 ответа
(Это может быть больше теоретического интереса.) NSPointerArray
соответствует NSFastEnumeration
протокол, это только for (id object in collection)
языковая конструкция, которую нельзя использовать с произвольными указателями, которые не являются указателями Objective-C.
Но вы можете получить целую кучу указателей из массива, вызвав NSFastEnumeration
метод countByEnumeratingWithState:objects:count:
непосредственно. Это немного сложно, потому что этот метод не должен заполнять предоставленный буфер (как объяснено здесь: как внутри цикла работает внутренне - Цель C - Основа).
Вот простой пример того, как это будет работать:
__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);
}
Так что это не поможет сделать код проще, и вы, вероятно, захотите придерживаться своего явного цикла.
Но для больших массивов это может повысить производительность, поскольку указатели "выбираются" в пакетном порядке из массива, а не каждого указателя в отдельности.
Синтаксис for (... in ...) в этом случае не будет работать, потому что Segment - это структура, а не объект Objective C. Ваш второй цикл должен работать.