Реализация NSFastEnumerator: EXC_BAD_ACCESS при итерации с for… in - PullRequest
4 голосов
/ 19 августа 2011

У меня есть структура данных, которую я хотел перечислить.Я попытался реализовать NSFastEnumerator моего объекта следующим образом:

- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state 
                                  objects:(__unsafe_unretained id [])buffer 
                                    count:(NSUInteger)len {

    NSUInteger c = 0;
    while (c < len) {
        id obj = [self objectAtIndex:state->state];
        if (obj == nil) break;
        buffer[c] = obj;
        c++;
        state->state++;
    }
    state->itemsPtr = buffer;
    state->mutationsPtr = nil;
    return c;
}

Если я использую objectAtIndex напрямую, мой объект работает правильно.Я получаю ноль, когда индекс не существует.Но когда я затем использую цикл for:

for (Pin *pin in coll) { ... }

, код проходит через вышеупомянутую функцию в порядке и заполняет состояние, как представляется, действительными значениями и возвращает количество объектов, тогда я получаю ошибку EXC_BAD_ACCESSв самом операторе for.

Что я делаю не так в этой реализации?

Ответы [ 3 ]

2 голосов
/ 08 июля 2013

У меня просто были похожие проблемы, и после более тщательного изучения FastEnumerationSample от Apple эта часть (которую я пропустил) бросилась на меня:

// We are not tracking mutations, so we'll set state->mutationsPtr to point into one of our extra values,
// since these values are not otherwise used by the protocol.
// If your class was mutable, you may choose to use an internal variable that is updated when the class is mutated.
// state->mutationsPtr MUST NOT be NULL.
state->mutationsPtr = &state->extra[0];

Важная часть: state->mutationsPtr НЕ ДОЛЖНА БЫТЬ НУЛЬ . Я просто использовал приведенную в качестве примера строку, и она сработала как шарм!

1 голос
/ 19 августа 2011

Я предполагаю, что вы используете ARC. Проблема может заключаться в том, что buffer является массивом __unsafe_unretained объектов, поэтому ARC может их перевыпускать. Но как выглядит ваш objectAtIndex: метод? Это не должно быть проблемой, если вы возвращаете объекты, которые гарантированно будут живы, по крайней мере, до тех пор, пока сам ваш объект.

0 голосов
/ 25 февраля 2012

Вместо:

id obj = [self objectAtIndex:state->state];

использовать

__unsafe_unretained id  = [self objectAtIndex:state->state];
...