Нужно переопределить drawrect, если ваш UIView является просто контейнером?

Согласно документации Apple, «подклассы не должны переопределять - [UIView drawRect:], если подкласс является контейнером для других представлений».

У меня есть собственный подкласс UIView, который на самом деле является просто контейнером для других представлений. Однако содержащиеся в нем представления не отображаются. Вот соответствующий код, который устанавливает собственный подкласс UIView:

- (id)initWithFrame:(CGRect)frame
{
    if ((self = [super initWithFrame:frame]))
    {
        // Consists of both an "on" light and an "off" light. We flick between the two depending upon our state.
        self.onLight = [[[LoyaltyCardNumberView alloc] initWithFrame:frame] autorelease];
        self.onLight.backgroundColor = [UIColor clearColor];
        self.onLight.on = YES;
        [self addSubview:self.onLight];

        self.offLight = [[[LoyaltyCardNumberView alloc] initWithFrame:frame] autorelease];
        self.offLight.backgroundColor = [UIColor clearColor];
        self.offLight.on = NO;
        [self addSubview:self.offLight];

        self.on = NO;
    }
    return self;
}

Когда я запускаю код, отображающий этот пользовательский UIView, ничего не отображается. Но когда я добавляю метод drawRect ...

    - (void)drawRect:(CGRect)rect
    {
        [self.onLight drawRect:rect];
        [self.offLight drawRect:rect];
    }

... отображаются подвиды. (Ясно, что это неправильный способ делать это не только потому, что это противоречит тому, что говорится в документации, но и потому, что он всегда отображает оба подпредставления, полностью игнорируя какой-то другой код в моем UIView, который устанавливает скрытое свойство одно из представлений, он игнорирует z-порядок и т. д.)

Во всяком случае, главный вопрос: почему мои подпредставления не отображаются, когда я не переопределяю drawRect :?

Спасибо!

ОБНОВЛЕНИЕ:

Чтобы убедиться, что проблема не в моих пользовательских подпредставлениях, я также добавил UILabel. Итак, код гласит:

- (id)initWithFrame:(CGRect)frame
{
    if ((self = [super initWithFrame:frame]))
    {
        // Consists of both an "on" light and an "off" light. We flick between the two depending upon our state.
        self.onLight = [[[LoyaltyCardNumberView alloc] initWithFrame:frame] autorelease];
        self.onLight.backgroundColor = [UIColor clearColor];
        self.onLight.on = YES;
        [self addSubview:self.onLight];

        self.offLight = [[[LoyaltyCardNumberView alloc] initWithFrame:frame] autorelease];
        self.offLight.backgroundColor = [UIColor clearColor];
        self.offLight.on = NO;
        [self addSubview:self.offLight];

        self.on = NO;

        UILabel* xLabel = [[[UILabel alloc] initWithFrame:frame] autorelease];
        xLabel.text = @"X";
        [self addSubview:xLabel];
    }
    return self;

«X» тоже не отображается.

ОБНОВЛЕНИЕ 2:

Вот код, который вызывает мой пользовательский UIView (OffOnLightView):

            // Container for all of the OffOnLightViews...
            self.stampSuperView = [[[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)] autorelease];
            [self.view addSubview:self.stampSuperView];

            // Draw the stamps into the 'stamp superview'.
            NSInteger numberOfCardSpaces = (awardType == None) ? 3 : 10;
            for (NSInteger i = 1; i <= numberOfCardSpaces; i++)
            {
                OffOnLightView* newNumberView = [[[OffOnLightView alloc] initWithFrame:[self frameForStampWithOrdinal:i awardType:awardType]] autorelease];
                newNumberView.on = (i <= self.place.checkInCount.intValue);
                newNumberView.number = [NSString stringWithFormat:@"%d", i];
                [self.stampSuperView addSubview:newNumberView];
            }

person Greg Maletic    schedule 03.06.2010    source источник
comment
Можете ли вы опубликовать код того, как создается / отображается родительское представление?   -  person rickharrison    schedule 03.06.2010
comment
@rickharrison См. Обновление 2 выше. Спасибо.   -  person Greg Maletic    schedule 03.06.2010
comment
Что произойдет, если вы установите onlight.backgroundColor = [UIColor greenColor]? Вы что-нибудь видите?   -  person progrmr    schedule 03.06.2010


Ответы (2)


Фрейм ваших вложенных представлений должен быть инициализирован границами родительского uiview. Подпредставления находятся в другой системе координат, относящейся к фрейму родительского элемента.

self.onLight = [[[LoyaltyCardNumberView alloc] initWithFrame:self.bounds] autorelease];
person progrmr    schedule 03.06.2010
comment
Я сделал ту же ошибку пару раз с Popovers. - person progrmr; 03.06.2010

Никогда не вызывайте -drawRect: вручную. Если вам нужно принудительно перерисовать, вызовите -setNeedsDisplay.

Я бы начал с отладки (точка останова или NSLog()) в -drawRect: методах двух подвидов, которые вы добавляете, чтобы убедиться, что они действительно выполняют отрисовку.

Также обратите внимание, как вы делаете оба подпредставления в полный размер (фрейм) содержащего представления и устанавливаете их фоновые цвета на очистку. Я собираюсь предположить, что это намеренно, но возможно, что они отображаются, но вы просто ничего не видите из-за того, что у них прозрачный фон.

person jbrennan    schedule 03.06.2010