Подтвердить что ты не робот

Автоматический подсчет ссылок: ошибка с быстрым перечислением

При обновлении приведенного ниже кода для использования автоматического подсчета ссылок для iOS 5 возникает ошибка, когда "state- > itemPtr" присваивается буфер при попытке выполнить Fast Enumeration, так что класс реализации может быть повторен с помощью "foreach". Ошибка, которую я получаю, - "Назначение" __autoreleasing id * 'to' __unsafe_unretained id * 'изменяет свойства сохранения/выпуска указателя ". См. Строку кода с комментарием.

/*
 * @see http://cocoawithlove.com/2008/05/implementing-countbyenumeratingwithstat.html
 * @see http://www.mikeash.com/pyblog/friday-qa-2010-04-16-implementing-fast-enumeration.html
 */
- (NSUInteger) countByEnumeratingWithState: (NSFastEnumerationState *)state objects: (id *)buffer count: (NSUInteger)bufferSize {
    NSUInteger arrayIndex = (NSUInteger)state->state;
    NSUInteger arraySize = [_tuples count];
    NSUInteger bufferIndex = 0;

    while ((arrayIndex < arraySize) && (bufferIndex < bufferSize)) {
        buffer[bufferIndex] = [_tuples objectAtIndex: arrayIndex];
        arrayIndex++;
        bufferIndex++;
    }

    state->state = (unsigned long)arrayIndex;
    state->itemsPtr = buffer; // Assigning '__autoreleasing id *' to '__unsafe_unretained id*' changes retain/release properties of pointer
    state->mutationsPtr = (unsigned long *)self;

    return bufferIndex;
}

Переменная _tuples в этом примере является переменной экземпляра типа NSMutableArray.

Как устранить эту ошибку?

4b9b3361

Ответ 1

Вам нужно сменить буфер на __unsafe_unretained:

- (NSUInteger) countByEnumeratingWithState: (NSFastEnumerationState *)state
                                   objects: (id __unsafe_unretained *)buffer
                                     count: (NSUInteger)bufferSize

источник

Изменить: простой способ избавиться от ошибки в mutationPtr:

state->mutationsPtr = &state->extra[0];

Ответ 2

Ziminji,

У меня была та же проблема, вот как я столкнулся с этим вопросом.

Я решил это, сохранив определение параметра objects как есть (например, сохраняя его как id *) и вместо этого сделав двойное литье с использованием указателя void.

Итак, хотя это порождает ошибки для меня:

state->itemsPtr = (__unsafe_unretained id *)buffer  // Error

Это прекрасно работало:

state->itemsPtr = (__unsafe_unretained id *)(void *)buffer  // No error

Отказ от ответственности: я не эксперт по АРК, и я не могу гарантировать, что это не вызовет проблем с подсчетом ссылок. Однако, похоже, он работает правильно в моем тестировании, и он определенно компилируется без предупреждений.

Кстати, я столкнулся с этой записью в блоге с двумя частями, которая охватывает "Быстрое перечисление" в хорошем объеме:

а также эту запись в блоге __unsafe_unretained: