Поддерживающий слой UIView - делегат - зомби

У меня есть класс UIView, который использует настраиваемый слой поддержки, производный от CALayer. то есть у меня есть статический метод layerClass, который возвращает класс моего настраиваемого класса CALayer.

+ (Class)layerClass
{
    return [CellLayer class];
}

В этом классе (CellLayer) я привел делегата к классу UIView, который содержит слой поддержки - в частности, в методе drawInContext: я делаю следующее:

CellClass* cell = (CellClass*)self.delegate;

(где CellCass - это подкласс UIView)

Кажется, это работает нормально, за исключением того, что иногда вызывается метод drawInContext:, а делегат является зомби (для NSZombieEnabled установлено значение TRUE).

Похоже, что происходит следующее: когда объект ячейки удаляется из своего супервизора (который является UIScrollView), ячейка освобождается до того, как высвобождается слой поддержки, и слой поддержки получает вызов drawInContext:. Заявления NSLog показывают, что в конечном итоге вызываются ОБЕИХ методы dealloc (то есть вызываются UIView и dealloc CALayer), но я не могу точно сказать, в каком порядке, поскольку приложение, использующее это, имеет десятки и десятки этих ячеек - я думаю, я мог бы измените NSLog, чтобы отображать адрес ячейки в консоли и сопоставить освобождение UIView и освобождение CALayer, но я не позаботился об этом.

Я ожидал, что слой поддержки будет выпущен до того UIView, который его содержит.

Это правильное поведение? Мой текущий обходной путь заключается в том, что в Dealloc UIView я устанавливаю флаг в фоновом слое (viewWasReleased), а в drawInContext я просто возвращаюсь, если этот флаг установлен.

Есть ли способ сделать это лучше и чище?


person Jordan    schedule 04.04.2011    source источник


Ответы (1)


сегодня у меня был тот же вопрос, и я наконец решил свою проблему.

Проблема заключалась в том, что когда вызывается метод dealloc, ваш CellLayer не уничтожается, потому что он имеет ссылку на текущий объект. (делегат) Итак, CALayer не уничтожается, а self.delegate - это освобожденный экземпляр. Зомби.

Я исправил это добавление в свой метод viewDidDisappear своего класса, и там я добавил следующий код:

if(cell != nil)
    cell.delegate = nil;

Затем, когда в моем объекте вызывается метод dealloc, в CALayer нет ссылки на него, поэтому с простым self.cell = nil; Объект CALayer будет уничтожен раньше, и у вас не будет проблем с делегатом.

person ccsakuweb    schedule 04.05.2011