Автоматический подсчет ссылок: ошибка с быстрым перечислением - PullRequest
13 голосов
/ 19 октября 2011

При обновлении приведенного ниже кода для использования автоматического подсчета ссылок для iOS 5 возникает ошибка, когда «state-> itemPtr» назначается буфер при попытке выполнить быстрое перечисление, так что реализующий класс можно итерировать с помощью «foreach "петля.Я получаю сообщение об ошибке: «Назначение __autoreleasing id *» на __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.

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

Ответы [ 2 ]

15 голосов
/ 19 октября 2011

Вам необходимо изменить буфер на __unsafe_unretained:

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

источник

Редактировать: простой способ избавиться от ошибки в mutationPtr:

state->mutationsPtr = &state->extra[0];
1 голос
/ 26 марта 2013

Ziminji,

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

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

Итак, пока это вызывает у меня ошибки:

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

Это сработалокрасиво:

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

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

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

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

...