Назначение делегата для подслоя CALayer выдает EXC_BAD_ACCESS? - PullRequest
7 голосов
/ 22 февраля 2012

Я пытаюсь использовать серию слоев CALay в качестве подслоев для вида, который требует немного более мелкого рисования, чем обычно.Я использовал CATiledLayer раньше, и я думал, что использование подслоев будет проще, если не одинаково привередливым.Я подумал, что выполняю [self.layer addSublayer:sublayer], устанавливаю делегат этого нового подслоя и затем рисую все, что хочу, в методе drawLayer:inContext:.Но, к моему большому удивлению, мое приложение падает на addSubview: (без IB) или где-то выше стека вызовов (при использовании IB).

Согласнодокументы ...

Ссылка CALayer , похоже, точно определяет, что я делаю, но каждый раз происходит сбой:

В iOS, если слой связан с объектом UIView, это свойство должно быть установлено на представление, которому принадлежит слой.

Но, очевидно, я что-то напортачил.К счастью, это легко воспроизводимо.Можете ли вы объяснить мне, как я должен использовать подслои с назначениями делегатов для получения правильных drawLayer:inContext: вызовов без сбоев?

Шаги для воспроизведения

Поместите это в класс пользовательского представления, помещенногона экране с Интерфейсным Разработчиком (или переписать инициализацию, которая будет называться initWithFrame:):

- (id)initWithCoder:(NSCoder *)aDecoder {
    self = [super initWithCoder:aDecoder];

    if (self) {
        CALayer *sublayer = [CALayer layer];
        sublayer.frame = self.layer.bounds;

        // Disable or enable this next line to 
        // resolve or trigger an EXC_BAD_ACCESS crash.
        // 
        sublayer.delegate = self;

        [self.layer addSublayer:sublayer];
        [self.layer setNeedsDisplay];
    }

    return self;
}

- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx {
    CGContextSetFillColorWithColor(ctx, [[UIColor greenColor] CGColor]);
    CGContextFillRect(ctx, self.bounds);
}

Если вы запустите этот код, ваше приложение вылетит.Следите за линией sublayer.delegate = self.Если вы отключите его, ваше приложение будет запущено, но метод drawLayer:inContext: никогда не будет вызываться для этого подслоя.

Что я делаю не так?

1 Ответ

15 голосов
/ 22 февраля 2012

Это не работает, потому что UIView, который вы подклассируете (я предполагаю, что это UIView), уже является делегатом своего собственного CALayer, он не может быть делегатом более чем одного CALayer одновременно. У этого поста есть еще несколько деталей:

Использование CALayer Delegate

...